背景
在我的应用程序中,我有一系列可以从另一个 View 添加的 friend 。我已经将这个 friend 数组存储在一个类中,该类是 ObservableObject
。 .在我的主视图中,FriendListView
, 我正在使用 ForEach
为用户添加的每个 friend 显示自定义 View 。
我无法添加到数组并让列表显示新项目。根据我能够理解和组合的内容,我尝试了两种不同的尝试。有人能够提供的任何帮助将不胜感激。我目前有显示第二个 View 的方法,我将在其中添加一个注释掉的新 friend ,并且一个自动保存新 friend 的方法作为导航栏项目存在。
尝试
尝试#1
如果在类初始化程序期间将 friend 附加到数组中,我就成功地显示了 friend 列表。基于我能够打印数组的内容但 UI 没有更新,调用类方法从另一个 View 添加到数组似乎有效。
这是通过使用 ForEach(0..<Array.count)
完成的。方法,但我在添加新项目后收到以下控制台错误。
错误
ForEach<Range<Int>, Int, HStack<TupleView<(Spacer, FriendView, Spacer)>>> count (4) != its initial count (3).
`ForEach(_:content:)` should only be used for *constant* data.
Instead conform data to `Identifiable` or use `ForEach(_:id:content:)` and provide an explicit `id`!
型号代码 struct Pet: Identifiable {
var id = UUID().uuidString
var name: String
var breed: String
}
class FriendModel: ObservableObject {
@Published var petList = [Pet]()
func addFriend(name: String, breed: String) {
petList.append(Pet(name: name, breed: breed))
}
init() {
petList.append(Pet(name: "Woofer", breed: "Dawg"))
petList.append(Pet(name: "Floofer", breed: "Dawg"))
petList.append(Pet(name: "Super", breed: "Dawg"))
// petList.append(Pet(name: "Dooper", breed: "Dawg"))
// petList.append(Pet(name: "Booper", breed: "Dawg"))
}
}
用户界面代码 struct FriendListView: View {
@EnvironmentObject var dataModel: FriendModel
@State private var displayAddFriendSheet = false
var body: some View {
GeometryReader { geo in
NavigationView {
ScrollView {
ForEach(0..<self.dataModel.petList.count) { pet in
HStack {
Spacer()
FriendView(
name: self.dataModel.petList[pet].name,
breed: self.dataModel.petList[pet].breed,
screenWidth: geo.size.width,
randomPic: Int.random(in: 1...2)
)
// FriendView(
// name: self.dataModel.petList[pet].name,
// breed: self.dataModel.petList[pet].breed,
// screenWidth: geo.size.width)
Spacer()
}
}
}// End of ScrollView
.navigationBarTitle(Text("Furiends"))
.navigationBarItems(trailing: Button(action: self.showAddFriend) {
Image(systemName: "plus")
}
)
.sheet(isPresented: self.$displayAddFriendSheet) {
AddFriendView()
}
}// End of NavigationView
}// End of GeometryReader geo1
}// End of body
func showAddFriend() {
// self.displayAddFriendSheet.toggle()
self.dataModel.addFriend(name: "Jax", breed: "Doodle")
print(dataModel.petList)
}// Enf of showAddFriend
}// End of FriendListView
尝试#2在看到第一次尝试的错误后,我阅读了如何跳过范围并仅提供数组作为
ForEach
的一部分因为我遵守Identifiable
Pet
中带有我的 UUID 的协议(protocol)结构。模型代码与我的第一次尝试相同,我更新的 UI 代码如下。请注意,唯一的变化是 ForEach 但我收到以下错误:错误
Cannot convert value of type '[Pet]' to expected argument type 'Range<Int>'
用户界面代码 struct FriendListView: View {
@EnvironmentObject var dataModel: FriendModel
@State private var displayAddFriendSheet = false
var body: some View {
GeometryReader { geo in
NavigationView {
ScrollView {
ForEach(self.dataModel.petList) { pet in // <--- Changed to directly reference the array
HStack {
Spacer()
FriendView(
name: self.dataModel.petList[pet].name,
breed: self.dataModel.petList[pet].breed,
screenWidth: geo.size.width,
randomPic: Int.random(in: 1...2)
)
// FriendView(
// name: self.dataModel.petList[pet].name,
// breed: self.dataModel.petList[pet].breed,
// screenWidth: geo.size.width)
Spacer()
}
}
}// End of ScrollView
.navigationBarTitle(Text("Furiends"))
.navigationBarItems(trailing: Button(action: self.showAddFriend) {
Image(systemName: "plus")
}
)
.sheet(isPresented: self.$displayAddFriendSheet) {
AddFriendView()
}
}// End of NavigationView
}// End of GeometryReader geo1
}// End of body
func showAddFriend() {
// self.displayAddFriendSheet.toggle()
self.dataModel.addFriend(name: "Jax", breed: "Doodle")
print(dataModel.petList)
}// Enf of showAddFriend
}// End of FriendListView
最佳答案
我假设其余的通过订阅访问的尝试会混淆编译器,至于 Pet
是 Identifiable
以下应该工作
ForEach(self.dataModel.petList) { pet in
HStack {
Spacer()
FriendView(
name: pet.name, // << pet is not index
breed: pet.breed, // << so access by property
screenWidth: geo.size.width,
randomPic: Int.random(in: 1...2)
)
// .. other code
关于ios - SwiftUI ForEach 未更新 ObservableObject 类数组的以下更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62379803/