[解決済み] SwiftUIアプリケーションでObservedObjectの配列が更新されないのはなぜか?
2023-08-02 11:07:49
質問
私はSwiftUIで遊んでいて、どのように
ObservableObject
がどのように機能するかを理解しようとしています。私は、配列の
Person
オブジェクトの配列があります。新しい
Person
を配列に追加すると、それがビューに再ロードされますが、 既存の
Person
の値を変更しても、ビューに再ロードされません。
// NamesClass.swift
import Foundation
import SwiftUI
import Combine
class Person: ObservableObject,Identifiable{
var id: Int
@Published var name: String
init(id: Int, name: String){
self.id = id
self.name = name
}
}
class People: ObservableObject{
@Published var people: [Person]
init(){
self.people = [
Person(id: 1, name:"Javier"),
Person(id: 2, name:"Juan"),
Person(id: 3, name:"Pedro"),
Person(id: 4, name:"Luis")]
}
}
struct ContentView: View {
@ObservedObject var mypeople: People
var body: some View {
VStack{
ForEach(mypeople.people){ person in
Text("\(person.name)")
}
Button(action: {
self.mypeople.people[0].name="Jaime"
//self.mypeople.people.append(Person(id: 5, name: "John"))
}) {
Text("Add/Change name")
}
}
}
}
を追加する行をアンコメントすると、新しい
Person
(John)を追加すると、Jaimeの名前が正しく表示されますが、名前だけを変更すると、これはViewに表示されません。
私は何か間違ったことをしているのか、あるいは、どのように
ObservedObjects
がどのように配列で動作するのかを理解していないのかもしれません。
どのように解決するのですか?
クラスの代わりに構造体を使用することができます。構造体の値のセマンティクスにより、人の名前の変更はPerson構造体自体の変更と見なされ、この変更はpeople配列の変更でもあるため、@Publishedで通知が送信され、Viewの本文が再計算されることになります。
import Foundation
import SwiftUI
import Combine
struct Person: Identifiable{
var id: Int
var name: String
init(id: Int, name: String){
self.id = id
self.name = name
}
}
class Model: ObservableObject{
@Published var people: [Person]
init(){
self.people = [
Person(id: 1, name:"Javier"),
Person(id: 2, name:"Juan"),
Person(id: 3, name:"Pedro"),
Person(id: 4, name:"Luis")]
}
}
struct ContentView: View {
@StateObject var model = Model()
var body: some View {
VStack{
ForEach(model.people){ person in
Text("\(person.name)")
}
Button(action: {
self.mypeople.people[0].name="Jaime"
}) {
Text("Add/Change name")
}
}
}
}
あるいは(お勧めしませんが)。
Person
はクラスなので、参照型になります。それが変化すると
People
配列は変更されないので、サブジェクトからは何も出力されません。しかし、手動で呼び出すことで、それを知らせることができます。
Button(action: {
self.mypeople.objectWillChange.send()
self.mypeople.people[0].name="Jaime"
}) {
Text("Add/Change name")
}
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン