import SwiftUI import Combine let initToDos = [ ToDo(title: "タスク1", done: false), ToDo(title: "タスク2", done: true), ] struct ToDo : Identifiable{ let id = UUID() var title: String var done: Bool } struct ToDoList { var todos: [ToDo] = initToDos var completedToDos: [ToDo] { get{ return todos.filter { $0.done } } } var unCompletedToDos: [ToDo] { get{ return todos.filter { !$0.done } } } func toggle(id: UUID){ // TODO } func append(title: String){ // TODO } } struct ContentView: View { var body: some View { VStack{ ToDoView() } } } class AsyncState: ObservableObject { var f: () -> Data @Published var isLoading = false @Published var error: Error? @Published var data: Data? init(f: @escaping () -> Data) { self.f = f } func get() { self.isLoading = true DispatchQueue.main.asyncAfter(deadline: .now() + 1) {// 1s sleep self.data = self.f() self.isLoading = false } } } struct ToDoView: View { @StateObject private var state = AsyncState { return ToDoList() // APIコール } var body: some View { ZStack { VStack{ Button(action: { state.todoList?.append(title: "新タスク") }){ Text("追加") } Text("全ToDo") ToDoListView(todos: state.todoList?.todos ?? [], toggle: state.todoList?.toggle) Text("未完了ToDo") ToDoListView(todos: state.todoList?.unCompletedToDos ?? [], toggle: state.todoList?.toggle) Text("完了済みToDo") ToDoListView(todos: state.todoList?.completedToDos ?? [], toggle: state.todoList?.toggle) }.onAppear { state.get() } if state.isLoading { ProgressView() } } } } struct ToDoListView: View { let todos: [ToDo] let toggle: ((UUID) -> Void)? var body: some View { VStack{ List { ForEach(todos) { todo in ToDoRow(todo: todo, toggle: toggle) } } } } } struct ToDoRow: View { let todo: ToDo let toggle: ((UUID) -> Void)? var body: some View { HStack { Text(todo.title) Spacer() Button(action: { toggle?(todo.id) }){ if (todo.done) { Image(systemName: "checkmark.square.fill") .foregroundColor(.green) }else { Image(systemName: "square") } } } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }