Avatar
Avatar
We
SwiftUIについてご質問させてください。 以下コードはTODOリストを実装したものです。TodoItemには完了/未完了を表すチェックボックスがあり、完了した項目は下になるようソートしています。 ですがObservableObjectがネストしているためチェックボックスの変更通知がContentViewまで届かず、リストが再描画されません。 この問題についてはobjectWillChangeとコールバック関数を組み合わせて解決しましたが、どうもSwiftUIの設計思想に反している気がします。 もっとSwiftの流儀に則ったうまい解決方法はありますでしょうか。 import SwiftUI struct ContentView: View { @StateObject var viewModel = TodoList() var body: some View { List { Button("Add Item") { viewModel.add() } ForEach(viewModel.items.sorted { !$0.completed && $1.completed }) { TodoItemView(viewModel: $0) } } } } class TodoList: ObservableObject { @Published var items: [TodoItem] = [] func add() { items.append(TodoItem(text: "item: \(items.count)") { self.objectWillChange.send() }) } } class TodoItem: ObservableObject, Identifiable { @Published var completed = false { didSet { onChanged() } } @Published var text: String private let onChanged: () -> Void init(text: String, onChanged: @escaping () -> Void) { self.text = text self.onChanged = onChanged } } struct TodoItemView: View { @StateObject var viewModel: TodoItem var body: some View { HStack { Button(action: { viewModel.completed.toggle() }, label: { Image(systemName: viewModel.completed ? "checkmark.square.fill" : "square") }) TextField("", text: $viewModel.text) } } }
ObservableObjectがネストしているためチェックボックスの変更通知がContentViewまで届かず(略) どうもSwiftUIの設計思想に反している気がします。
こういうの悩ましいですよね。もうすぐObservation(↓)が追加され、それを利用すればネストしたモデルの変更も通知されるようになるので、iOSのバージョンが許せばそれを利用するのが良いかもしれません。 https://developer.apple.com/videos/play/wwdc2023/10149/ https://github.com/apple/swift-evolution/blob/main/proposals/0395-observability.md
Simplify your SwiftUI data models with Observation. We'll share how the Observable macro can help you simplify models and improve your...
This maintains proposals for changes and user-visible enhancements to the Swift Programming Language. - apple/swift-evolution
👏 1
🙇‍♂️ 1