如何在 SwiftUI 中使用 ObservableObject 加载数据?

How do I load data using ObservableObject in SwiftUI?

我正在尝试将一个应用程序从 UIKit 转换到 SwiftUI,这取决于基本的 DynamoDB 资源,但是我在强制视图在数据添加到列表时刷新时遇到了障碍。我已经在这组代码上尝试了几个小时尝试不同的东西,我想我可能会看看是否有人知道为什么 'SessionsData' 似乎被丢弃并且不会累积 'Sessions' 对象。

有没有人有什么快速的想法???

class SessionsData: ObservableObject {

    let didChange = PassthroughSubject<SessionsData, Never>()
    @Published var data: [Sessions] = [] {
        didSet {
            didChange.send(self)
        }
    }

    init() {
        load()
    }

    func load() {
        let dynamoDBObjectMapper = AWSDynamoDBObjectMapper.default()
        let scanExpression = AWSDynamoDBScanExpression()
        scanExpression.limit = 20

        var temp : [Sessions] = []

        dynamoDBObjectMapper.scan(Sessions.self, expression: scanExpression).continueWith(block: { (task:AWSTask<AWSDynamoDBPaginatedOutput>!) -> Any? in
            if let error = task.error as NSError? {
                 print("The request failed. Error: \(error)")
             } else if let paginatedOutput = task.result {
                for session in paginatedOutput.items as! [Sessions] {
                    print("Item Found")
                    temp.append(session)
                }
                DispatchQueue.main.async {
                    self.data = temp
                    self.didChange.send(self)
                }
             }
            print(self.data.count)
            return true
         })
    }
}
struct Events: View {

    @ObservedObject var sessionsData = SessionsData()


    var body: some View {...}
}

我没有使用 DynamoDB 的经验,但这里有一些来自 SwiftUI / Combine 的观点。在 ObseravbleObject 中有一个重要的变化,现在用 objectWillChange 声明,然后在 willSet 中发送 newValue:

class SessionsData: ObservableObject {

    public let objectWillChange = PassthroughSubject<[Sessions], Never>()

    public private(set) var items: [Sessions] = [] {
        willSet {
            objectWillChange.send(newValue)
        }
    }

    init() {
        self.items = []
    }

    public func load() {
        let dynamoDBObjectMapper = AWSDynamoDBObjectMapper.default()
        let scanExpression = AWSDynamoDBScanExpression()
        scanExpression.limit = 20

        var temp: [Sessions] = []

        dynamoDBObjectMapper
            .scan(Sessions.self,
                  expression: scanExpression)
            .continueWith(block: { (task:AWSTask<AWSDynamoDBPaginatedOutput>!) -> Any? in
                if let error = task.error as NSError? {
                   print("The request failed. Error: \(error)")
                } else if let paginatedOutput = task.result,
                    let sessions = paginatedOutput.items as? [Sessions] {
                    temp.append(contentsOf: sessions)
                }
                DispatchQueue.main.async {
                    self.items = temp
                }
            }
            return true
         })
    }
}

对于 UI 部分,您只需调用上面在 .onApear() 中定义的 load() 方法,其他一切都会神奇地发生:

结构事件:查看{

@ObservedObject var sessionsData: SessionsData

var body: some View {
    List {
        ForEach(self.sessionsData.items) { session in
            Text(session.name) // or something of that kind
        }
    }   .onAppear(perform: { self.sessionsData.load() })
}

}

看来您使代码过于复杂了。 PassthroughSubject 是不必要的。每当您更改 @Published 属性 时,它应该会触发更新。

class SessionsData: ObservableObject {

    @Published var data: [Sessions] = []

    init() {
        load()
    }

    func load() {
        let dynamoDBObjectMapper = AWSDynamoDBObjectMapper.default()
        let scanExpression = AWSDynamoDBScanExpression()
        scanExpression.limit = 20

        var temp : [Sessions] = []

        dynamoDBObjectMapper.scan(Sessions.self, expression: scanExpression).continueWith(block: { (task:AWSTask<AWSDynamoDBPaginatedOutput>!) -> Any? in
            if let error = task.error as NSError? {
                 print("The request failed. Error: \(error)")
             } else if let paginatedOutput = task.result {
                for session in paginatedOutput.items as! [Sessions] {
                    print("Item Found")
                    temp.append(session)
                }
                DispatchQueue.main.async {
                    self.data = temp
                }
             }
            print(self.data.count)
            return true
         })
    }
}