SwiftUI/Combine and RealmSwift.List Appending

Problem Context:

  • SwiftUI/Combine
  • Implementation based on RealmItems sample code

Problem:

    struct SyncGroupsPage: View {
       ...
       @ObservedObject var repository = SyncGroupRepository.shared
       ...
       var body: some View {
        ...
        Button(action: { _ = repository.addSyncGroupToCollection(name: "syncGroup=\(String.random(10))") }) ...
        }
    }

Repository:

    class SyncGroupRepository: ObservableObject {
    ...
        @Published var syncGroups: RealmSwift.List<SyncGroup>?
        func addSyncGroupToCollection(name: String) -> SyncGroup {
            let syncGroup = SyncGroup(name: name)
            try! state.user?.realm?.write {
                self.syncGroups?.append(syncGroup)
            }
            return syncGroup
        }
    ...
    }

Persistence is working as expected and if I leave the SyncGroupsPage view and come back in I see the updated values rendered.

syncGroups in the repository aren’t publishing any events when an append occurs. How should I modify the pattern?

Hi Michael,

Realm-Cocoa 10.6 made working with Realm from SwiftUI views much easier – this meetup recording goes into how to take advantage of the new features (if you’re not using Realm Sync then you can skip the discussions on partitions).

Here’s an example where I want to work with a realm for a specific partition ( “my-partition-key-value”) and so I inject it into the environment, you can skip that if you’re working with the default Realm:

struct ParentView: View {
   var body: some View {
       ChildView()
           .environment(\.realmConfiguration,
app.currentUser!.configuration(partitionValue: "my-partition-key-value"))
   }
}

struct ChildView: View {
   var body: some View {
       GrandChildView()
   }
}

struct GrandChildView: View {
   @ObservedResults(Item.self) var items
   @Environment(\.realm) var itemRealm
   var body: some View {
       List {
           ForEach(items) { item in
               NameView(item: item)
           }
       }
   }
}

struct NameView: View {
   @ObservedRealmObject var item: Item
  
   var body: some View {
       TextField("name", text: $item.name)
   }
}

In GrandChildView you can append to items using $items.append without needing to explicitly create a transaction, and the view will update.

1 Like