How to display Realm Results in SwiftUI List?
The data that you pass in List
or a ForEach
must conform to the Identifiable
protocol.
Either you adopt it in your Realm models or you use .identified(by:)
method.
Even with that, the View
won't reload if the data changes.
You could wrap Results
and make it a BindableObject
, so the view can detect the changes and reload itself:
class BindableResults<Element>: ObservableObject where Element: RealmSwift.RealmCollectionValue {
var results: Results<Element>
private var token: NotificationToken!
init(results: Results<Element>) {
self.results = results
lateInit()
}
func lateInit() {
token = results.observe { [weak self] _ in
self?.objectWillChange.send()
}
}
deinit {
token.invalidate()
}
}
And use it like:
struct ContentView : View {
@ObservedObject var dogs = BindableResults(results: try! Realm().objects(Dog.self))
var body: some View {
List(dogs.results.identified(by: \.name)) { dog in
DogRow(dog: dog)
}
}
}
What is the right way to present data from Realm in SwiftUI List
Probably you meant this
ForEach(allUsers, id:\.self) { user in
Text(user.name)
}
How can I properly map RealmDB Results objects to SwiftUI Lists?
Realm objects are live an autoupdating this is why they crash when you try to hold onto a deleted object. Instead of giving your publish subject the Realm.Object map it to a struct that has only the fields you need to use and use that array to drive SwiftUI.
struct Event: Identifiable {
var id: String
var name: String
var date: Date
}
final class DBData: ObservableObject {
private var notificationTokens: [NotificationToken] = []
var events = try! Realm().objects(ADMEvent.self)
@Published var publishedEvents: [ADMEvent] = []
init() {
// Observe changes in the underlying model
self.notificationTokens.append(posts.observe { _ in
self.publishedEvents = events.map { Event(id: $0.id, name: $0.name, date: $0.date)}
})
}
}
How to use Realm with SwiftUI
Sure, it's very simple, use the module identifier as prefix like this :
let members = RealmSwift.List<Member>()
Now to the second part of your question. It's easy to encapsulate a Realm object (or list, or resultset) in an BindableObject
:
final class DBData: BindableObject {
let didChange = PassthroughSubject<DBData, Never>()
private var notificationTokens: [NotificationToken] = []
var posts = Post.all
init() {
// Observe changes in the underlying model
self.notificationTokens.append(posts.observe { _ in
self.didChange.send(self)
})
self.notificationTokens.append(Message.all.observe { _ in
self.didChange.send(self)
})
}
}
If you "link" a DBData
instance to a SwiftUI View
by either using @ObjectBinding
or @EnvironmentObject
the UI will be refreshed and the new value for posts
(in our example here) will be available each time the underlying realm changes.
Realm with SwiftUI Returning List ShoppingItem
It conflicts with SwiftUI.List
, so you need to add module explicitly
var items: RealmSwift.List<ShoppingItem>
SwiftUI App Shows Realm Changes but Not New Objects
Realm Results objects are live-updating objects and always reflect the current state of those objects in Realm.
However, if you cast your Realm Results object to an array
items = Array(results)
It 'disconnects' those objects ( the results ) from Realm and it (they) are no longer live updating.
Additionally Realm Results objects are lazily-loaded, meaning that they are only loaded into memory when needed so thousands of objects take up almost no space.
Storing them in an array changes that - they are all loaded into memory and could overwhelm the device.
Best practice is to leave Realm Collections (Results, Lists) as that type of object throughout the duration of using them instead of casting to an array.
Related Topics
How to Make the Memberwise Initialiser Public, by Default, for Structs in Swift
Custom Swift Encoder/Decoder for the Strings Resource Format
How to Detect Vertical Planes in Arkit
Implicitly Lazy Static Members in Swift
Implementing a Drag-And-Drop Zone in Swift
Swift - Firebase Search in Database
How to Avoid Nested Navigation Bars in Swiftui
Could Not Find an Overload for '/' That Accepts the Supplied Arguments
How to Make Keyboard Dismiss When I Press Out of Searchbar on Swift
Nstextfield, Change Text in Swift
Convert Generic Free Function into Array Extension
How to Install Xcode on an External Hard Drive Along with the iPhone Simulator.App
Grab Frames from Video Using Swift