Reputation: 1907
Based on the examples provided by the Realm team, I have instantiated the realm and bind it to a class variable called 'realm' like this:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let realm = try! Realm()
I think it makes sense and makes the code more readable. However, my project is in it's early stage, the objects are changing quite a lot and I am trying to avoid performing migrations with this:
Realm.Configuration.defaultConfiguration.deleteRealmIfMigrationNeeded = true
Naturally this leads to trouble since I am trying to delete a Realm file after opening the Realm which is excplicitly forbidden in the docs. I have followed similar design pattern in my UIViewController classes as well, which makes refactoring a bit cumbersome.
The question is:
Is it bad practice to bind Realm instance to a class property as I have done? Should I always reference to Realm with let realm = try! Realm() block when I need to read my objects? Or is there some way to delete the Realm without deleting all the class wide realm instances?
Thank you 🙏
Upvotes: 0
Views: 383
Reputation: 15991
When you call try! Realm()
, Realm will internally store a cached reference to the instantiated Realm
object. That way, calling try! Realm()
on subsequent times will recycle that instance.
As such, it's generally considered best practice to not store Realm
instances as properties of long-lived objects, like the app delegate, and to only call try! Realm()
at the times when you actually need it.
You should configure your defaultConfiguration
as early as you can in your app delegate's execution.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
// Configure the default Realm
let configuration = Realm.Configuration()
configuration.deleteRealmIfMigrationNeeded = true
Realm.Configuration.defaultConfiguration = configuration
return true
}
This way, any calls to Realm()
after the fact will incorporate the delete upon migration logic. There's no reason to save a copy of Realm
before then.
If you're using storyboards, sometimes let realm = try! Realm()
as a property in a UIViewController
subclass may end up getting called before the app delegate has had a chance to fire. In which case, you can manually set up the storyboard logic in the app delegate too, after Realm has been configured.
Upvotes: 1
Reputation: 5664
I use this pattern:
Singleton DataManager
which is used to manage Realm
access. It can wrap all the try
s, for example:
class DataManager {
static let shared = DataManager()
func add(_ object: Object, update: Bool = true) {
do {
let realm = try Realm()
try realm.write {
realm.add(object, update: update)
}
} catch {
print (error)
}
}
...Other shared Realm methods...
}
I also have a MigrationManager
singleton, which as the name suggests, handles Realm migrations. It's method get called very early - well before DataManager
methods are called
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
...
MigrationManager.shared.migrate()
...
}
some MigrationManager
code
class MigrationManager {
static let shared = MigrationManager()
let schemaVersion: UInt64 = 3
private var migrationBlock: MigrationBlock? {
return { migration, oldSchemaVersion in
...
}
}
func migrate() {
let config = Realm.Configuration(
schemaVersion: schemaVersion,
migrationBlock: migrationBlock)
Realm.Configuration.defaultConfiguration = config
}
}
Upvotes: 1