Realm With SwiftUI
Realm
Realm is MongoDB for Local Device, Object Oriented Database.
To use this Database, you should have Xcode 12.4 or later.
and your app should target iOS 15 or later.
Install
It is very simple to install Realm on your app.
In this article, I will use only CocoaPods
pod ‘RealmSwift’, ‘~>10’
SwiftUI requires RealmSwift 10.19.0 or later.
Import
To use Realm SDK in your Swift code, I should import RealmSwift Package.
import RealmSwift
Model
My model is like this, it was used in the last article.
To use Realm, I tried to convert my model like this.
However the error raised will be like this.
It’s mean was that I had to create constructors.
Despite defining a constructor, XCode complained to me.
I don’t know why, but I had to create default constructor.
override init(){
super.init()
}
ObjectKeyIdentifiable is like this.
Actually ObjectId property is not required.
Embed Default Objects
I generated default alarm list like this.
However I need to prepare initial rows, to use Realm.
So I modified ResourceLoader like below.
To load rows from Realm, I had to define the root Realm object first.
Realm()
You can Realm with configurations, but I will not talk about it in this article.
With the root object I can select rows from default Realm Database.
let storedAlarms = self.realm.objects(AlarmModel.self)
This is like select * from AlarmModel.
storedAlarms is not array, so we have to convert to array.
return storedAlarms.compactMap{ $0 }
storedAlarms would be empty, because I didn’t insert rows yet.
Inserting is very easy, just add in write block.
try? self.realm.write {
self.realm.add(defaultAlarms)
}
Transaction
You may see the error when you trying to modify rows.
Thread 1: “Attempting to modify object outside of a write transaction — call beginWriteTransaction on an RLMRealm instance first.”
To solve the error, use Write block.
It will create a transaction automatically.
Now I can manage my alarm list with Realm Database.
Advanced
where
I mentioned that storedAlarms is not array.
It’s mean storedAlarms is query, so you can give condition before fetching rows.
However you can’t use fields as field type
Thread 1: “Unable to parse the format string \”enabled\””
Because fields in the condition are not values.
Lazy Write
Document say ‘Results to a query are not copies of your data’.
It’s mean if you modify object, it will be update database immediately.
So if we want to update later(etc, save button), we have to store modifications to another object(not realm object)?
Fortunately Realm provides begin/commitWrite to update objects lazy.
We can use begin/commitWrite instead of write block.
Of course, You can discard modifications with calling cancelWrite method instead of commitWrite.
ResourceLoader.realm.beginWrite()self.alarm.enabled = self.enabledResourceLoader.realm.cancelWrite()
References
https://www.mongodb.com/docs/realm/sdk/swift/swiftui/
https://www.mongodb.com/docs/realm/sdk/swift/examples/filter-data/
https://www.mongodb.com/docs/realm/sdk/swift/fundamentals/live-queries/