【问题标题】:SwiftUI ForEach not updating following changes to the ObservableObject class arraySwiftUI ForEach 未更新 ObservableObject 类数组的以下更改
【发布时间】:2020-10-04 08:50:03
【问题描述】:

背景

在我的应用程序中,我有一组可以从另一个视图添加的朋友。我已经将这组朋友存储在一个ObservableObject 的类中。在我的主视图FriendListView 中,我使用ForEach 为用户添加的每个朋友显示自定义视图。

我无法添加到数组并让列表显示新项目。根据我能够理解和组合的内容,我尝试了两种不同的尝试。有人能够提供的任何帮助将不胜感激。我目前有显示第二个视图的方法,我将在其中添加一个注释掉的新朋友,并且有一个自动保存新朋友的方法作为导航栏项目存在。

尝试

尝试 #1

如果在类初始化程序期间将朋友附加到数组中,我就成功地显示了朋友列表。基于我能够打印数组的内容但 UI 没有更新,调用类方法以从另一个视图添加到数组似乎有效。

这是通过使用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 的一部分,因为我在 @987654330 中使用我的 UUID 遵守 Identifiable 协议@结构。模型代码与我的第一次尝试相同,我更新的 UI 代码如下。请注意,唯一的变化是 ForEach,但我收到以下错误:

错误 Cannot convert value of type '[Pet]' to expected argument type 'Range&lt;Int&gt;'

界面代码

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

【问题讨论】:

    标签: ios swift xcode swiftui observableobject


    【解决方案1】:

    我认为通过订阅访问的剩余尝试会混淆编译器,因此只要 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
    

    【讨论】:

    • 我能够解决编译器问题并加载初始列表。我现在可以添加到列表中,但列表不反映更改。控制台中也没有警告。关于为什么会这样的任何想法?我的 dataModel 被创建为@EnvironmentObject var dataModel: FriendModel,我在我的 SceneDelegate 中将该类的一个实例作为环境变量传递。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 2021-02-27
    • 2020-12-05
    • 2020-09-13
    • 2022-11-15
    • 1970-01-01
    • 2021-12-11
    相关资源
    最近更新 更多