arrays - SWIFTUI:使用 Array 属性创建类 - 符合 'ObservableObject' 。类(class)!不是结构体

标签 arrays swift swiftui observableobject

我需要创建符合 ObservableObject 协议(protocol)的类的 Array 属性。因为我将把它与过滤器、排序等一起使用 - 从表中选择记录以在 ListView 中显示

class SQS_Record: NSObject, ObservableObject {
    @Published final var __idx: Int = -1 
}

class Project: SQS_Record {
    @objc dynamic var name: String = ""         { willSet { objectWillChange.send() } }
}

class SQS_Table<RecordType: SQS_Record>: ObservableObject {
    @Published var records = [RecordType]()
    var rcount: Int {
        return records.count
    }
    subscript (index: Int) -> RecordType {
        get {
            return records[index]
        }
        set(item) {
            records[index] = item
        }
    }


Let projectsTbl = SQS_Table<Project>(...)

struct ProjectsListView: View {
    // This is ERROR line - below
    @StateObject private var itemsList = projectsTbl.records.sorted { $0.__idx < $1.__idx }        
        
    var body: some View {
        NavigationView {
            List() {
                // Список
                ForEach (itemsList, id: \.__id) { (proj: Project) in
                    ProjectElement(project: proj)
                }
                .onMove(perform: moveItem )
                .onDelete(perform: delItem )
            }
    …
}

错误:通用结构“StateObject”要求“[Project]”符合“ObservableObject”

最佳答案

如果我正确理解你的问题,你的数组的项目是类。您可以将数组声明为@State,但只有对数组本身的更改(添加、排序、删除)才会导致重新计算body

让我们尝试一下:

struct ArrayOfObservableObjects: View {
    @State private var store = (1 ... 5).map(Record.init)
    var body: some View {
        NavigationView {
            List(store) { record in
                Text(record.score.description)
            }
            .toolbar {
                HStack {
                    Button("Shuffle") {
                        store.shuffle()
                    }
                    Button("Change First") {
                        store.first?.score = 666
                    }
                    Button("Add") {
                        store.insert(Record(store.count + 1), at: 0)
                    }
                }
            }
        }
    }
}

正如您所看到的,“更改第一”按钮实际上更改了“记录”的“分数”,但这种修改不会显示。

如果您希望“发布”对数组每个元素的更改,则必须执行以下几个步骤:

  1. 使您的记录可观察:
class Record: ObservableObject, Identifiable {
    let id = UUID()
    @Published var score: Int
    init(_ score: Int) {
        self.score = score
    }
}
  • 将数组包装在 ObservableObject 中:
  • class RecordStore: ObservableObject {
        @Published var records: [Record] = (1 ... 5).map(Record.init)
    
    
  • 订阅数组每个元素的更改
  •     private var c: AnyCancellable?
        init() {
            subscribeToChanges()
        }
    
        func subscribeToChanges() {
            c = records
                .publisher
                .flatMap { record in record.objectWillChange }
                .sink { [weak self] in
                    self?.objectWillChange.send()
                }
        }
    }
    

    它有效。但是缺少了一些东西(如果我们添加一个新元素,它将不会被观察到)。所以要完成:

    class RecordStore: ObservableObject {
        @Published var records: [Record] = (1 ... 5).map(Record.init) {
            didSet {
                subscribeToChanges()    ///<<< HERE
            }
        }
    
        private var c: AnyCancellable?
        init() {
            subscribeToChanges()
        }
    
        func subscribeToChanges() {
            c = records
                .publisher
                .flatMap { record in record.objectWillChange }
                .sink { [weak self] in
                    self?.objectWillChange.send()
                }
        }
    }
    

    和 View :

    import Combine
    import SwiftUI
    
    struct ArrayOfObservableObjects: View {
        @StateObject var store = RecordStore()
        var body: some View {
            NavigationView {
                List(store.records) { record in
                    Text(record.score.description)
                }
                .toolbar {
                    HStack {
                        Button("Shuffle") {
                            store.records.shuffle()
                        }
                        Button("Change First") {
                            store.records.first?.score = 666
                        }
                        Button("Add") {
                            store.records.insert(Record(store.records.count + 1), at: 0)
                        }
                    }
                }
            }
        }
    }
    

    关于arrays - SWIFTUI:使用 Array 属性创建类 - 符合 'ObservableObject' 。类(class)!不是结构体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69033796/

    相关文章:

    javascript - 为什么javascript推送数组和定义数组不相等

    php - Woocommerce:从插件获取一些自定义购物车项目数据值

    swift - 所选图像不会更改之前显示的图像

    swift - 如何将特定内容从 Collection View 添加到另一个 Collection View ?

    ios - @Environment(\.dismiss) 错误导致弹出 View 在 iOS 15 中加载自身的新版本

    swift - SwiftUI添加倒立面膜

    c - 当传递给 C 中的函数时丢失 char**array 的内容

    java - instanceof 运算符在原始和包装器类型数组的情况下

    ios - 如何处理 SKShapeNode 子类中的触摸?

    arrays - 如何在 SwiftUI 中计算数组的总计、小计和平均值