Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
249 views
in Technique[技术] by (71.8m points)

Observe Collection Results in Realm with Combine and SwiftUI

I am trying out this quick start for SwiftUI and Combine in order to try and understand how to connect my Realm database to Combine.

The example observes a RealmSwift.List and keeps a table populated with its data. This is is a linked list to a child class. I'm wondering how to observe a Results collection so I can keep track of any changes to an entire Realm class.

For example, let's say I have a Workspace class:

class Workspace: Object, ObjectKeyIdentifiable{
  @objc dynamic var id = UUID().uuidString
  @objc dynamic var name = ""
  @objc dynamic var archived = false
}

In the state object, I can set up a Results<Workspace> variable like this:

class AppState: ObservableObject {
  @Published var workspaces: Results<Workspace>?
  var cancellables = Set<AnyCancellable>()
  
  init(){

    let realmPublisher = PassthroughSubject<Realm, Error>()

    realmPublisher
      .sink(receiveCompletion: { _ in }, receiveValue: { realm in
        //Get the Results
        self.workspaces = realm.objects(Workspace.self)
      })
      .store(in: &cancellables)

    realmPublisher.send(try! Realm())

    return
  }
}

But when it comes time to observe the object, I can't because Results isn't an object (I assume).

struct ContentView: App {
  @ObservedObject var state = AppState()
  var view: some View {
    ItemsView(workspaces: state.workspaces!)  
  }
  var body: some Scene {
    WindowGroup {
      view.environmentObject(state)
    }
  }
}

struct ItemsView: View {
  @ObservedObject var workspaces: Results<Workspace> //<!-- Error

  var body: some View {
    //...
  }
}

Xcode gives a syntax error on the workspaces property:

Property type 'Results' does not match that of the 'wrappedValue' property of its wrapper type 'ObservedObject'

Is it possible to observe a set of Results just like we can have a notification listener on a collection of Results?

question from:https://stackoverflow.com/questions/66055959/observe-collection-results-in-realm-with-combine-and-swiftui

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Technically, you could hook up a sink to state.workspaces (state.$workspaces.sink()), but in this case, I think you're overcomplicating the problem.

You already have an @ObservableObject in your ContentView (AppState) that is managing the results for you. So, change ItemsView to just take this as a parameter:

var workspaces: Results<Workspace>?

It doesn't need to be an @ObservedObject -- either way, whether it's getting observed in that view or it's parent view, it's going to get re-rendered. It does have to be optional here, since it's an optional value on your AppState, unless you want to keep passing it with the force unwrap (!), but that's generally a bad idea, since it'll crash if it ever is in fact nil.

Also, above, in your Realm code, make sure it's matching the tutorial that you were following. For example, you have Publisher.sink which should really be realmPublisher.sink


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...