Created
June 1, 2022 01:44
-
-
Save aerickson14/3e5a477672eab3301be4e162e1a37bf7 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
import Combine | |
struct ContentView: View { | |
var body: some View { | |
TaskList(tasks: [ | |
Task(id: 1, title: "Task 1", isCompleted: false), | |
Task(id: 2, title: "Task 2", isCompleted: false), | |
Task(id: 3, title: "Task 3", isCompleted: true), | |
Task(id: 4, title: "Task 4", isCompleted: false) | |
]) | |
} | |
} | |
struct TaskList: View { | |
@ObservedObject var tasks: ObservableArray<Task> | |
var pendingTasks: [Task] { | |
tasks.array.filter { !$0.isCompleted } | |
} | |
var completedTasks: [Task] { | |
tasks.array.filter { $0.isCompleted } | |
} | |
init(tasks: [Task]) { | |
self.tasks = ObservableArray(tasks) | |
} | |
var body: some View { | |
List { | |
ForEach(Sections.allCases) { section in | |
Section( | |
content: { | |
ForEach($tasks.array) { task in | |
if show(task.wrappedValue, for: section) { | |
TaskCell(task: task) | |
} | |
} | |
}, | |
header: { Text(section.rawValue) } | |
) | |
} | |
} | |
} | |
func show(_ task: Task, for section: Sections) -> Bool { | |
section == .pending && !task.isCompleted || section == .completed && task.isCompleted | |
} | |
} | |
class ObservableArray<T: ObservableObject>: ObservableObject { | |
@Published var array: [T] | |
private var cancellables = Set<AnyCancellable>() | |
init(_ array: [T]) { | |
self.array = array | |
observeChildrenChanges() | |
} | |
private func observeChildrenChanges() { | |
array.forEach { | |
$0.objectWillChange | |
.sink { _ in | |
self.objectWillChange.send() | |
} | |
.store(in: &cancellables) | |
} | |
} | |
} | |
struct TaskCell: View { | |
@Binding var task: Task | |
var body: some View { | |
Button( | |
action: { | |
task.isCompleted.toggle() | |
print("\(task.title) is now \(task.isCompleted)") | |
}, | |
label: { | |
HStack { | |
Text(task.title) | |
Spacer() | |
Image(systemName: task.isCompleted ? "checkmark.circle.fill" : "circle") | |
} | |
} | |
) | |
.buttonStyle(PlainButtonStyle()) | |
} | |
} | |
class Task: ObservableObject, Identifiable { | |
let id: Int | |
@Published var isCompleted: Bool | |
@Published var title: String | |
init(id: Int, title: String, isCompleted: Bool) { | |
self.id = id | |
self.title = title | |
self.isCompleted = isCompleted | |
} | |
} | |
enum Sections: String, CaseIterable, Identifiable { | |
case pending | |
case completed | |
var id: String { rawValue } | |
} | |
struct ContentView_Previews: PreviewProvider { | |
static var previews: some View { | |
TaskList( | |
tasks: [ | |
Task(id: 1, title: "Task 1", isCompleted: false), | |
Task(id: 2, title: "Task 2", isCompleted: false), | |
Task(id: 3, title: "Task 3", isCompleted: true), | |
Task(id: 4, title: "Task 4", isCompleted: false) | |
] | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment