Replace Realm file while app is running - ios

To implement the backup / restore feature, I am deleting the existing Realm database file and replacing it with the new database file with the same name. However, with the app still running it does not see the contents of the new database file. If I quit and relaunch the app, it does see the contents of the new database file. Is there any way to make the app see the new contents without having to relaunch it?

Much like deleting a Realm file from disk, it's only safe to replace a Realm file on disk if your application does not currently have the Realm file open.
From Realm's documentation on Deleting Realm files:
Because Realm avoids copying data into memory except when absolutely required, all objects managed by a Realm contain references to the file on disk, and must be deallocated before the file can be safely deleted. This includes all objects read from (or added to) the Realm, all List, Results, and ThreadSafeReference objects, and the Realm itself.
In practice, this means that deleting a Realm file should be done either on application startup before you have opened the Realm, or after only opening the Realm within an explicit autorelease pool, which ensures that all of the Realm objects will have been deallocated.
The reason for this is that Realm maintains an in-memory cache of open files, so attempting to open a file that's already open will result in a reference to the already-open file being returned. This open file will continue to refer to the original file on disk, even if it has since been replaced. Ensuring that all references to Realm accessor objects have been cleaned up means that Realm will not have an existing open file to return, and will instead open the file from disk.
In other words, you must make sure you have no references to Realm's accessor objects (Realm, Results, ThreadSafeReference or Object instances) at the point when you attempt to replace the Realm file. You must also make sure that any references you did have have since been deallocated (i.e., they're not lingering in a dispatch queue's default autorelease pool).
An alternative approach that may be easier to manage is to use a different path when you attempt to reopen the restored file. Since you're accessing a different path on disk you'll be guaranteed to open the new file. You'll still need to make sure you have no references to Realm's accessor objects since otherwise you'll get a weird mix of old and new data, but it won't be as critical that you ensure that the accessor objects were deallocated.

Related

Change Realm file without restarting application

I'm currently using dropbox to backup the Realm database file and when i need to restore, i just delete the old file and than put the new one from dropbox in its place, but to work i need to restart the application.
So, i'm looking a way to avoid the app restart.
You could delete the current files the way Realm suggests in the docs: https://realm.io/docs/swift/latest/#deleting-realm-files
Then nil your current Realm, write the new file to the right location in your file system and create a new Realm instance. Then reload your UI to show the new data.
You'll also have to be careful that your code is not holding references to objects in the previous Realm before it gets deleted.

On generating zip file of realm database its not having all data.

I have an issue with a realm database. I have an app which continues inserts data in the realm database. Now there is a scheduler which creates the a copy of zip file of this realm database in some interval of time. Now the problem is the zip file doesn't get the updated values. I am suspecting the realm's lock file might be preventing it. But I am not sure. Is there any way to get this thing done ?
As I understand you're making a backup of Realm file in some interval of time, right? So if you want to include all recent changes to backup you should make sure that all write transactions are committed before you make a copy.
You can also use -writeCopyToURL:encryptionKey:error: method to copy Realm to a temporary destination and then compress it if you need.

How to completely destroy and recreate a Realm database

I have an application using Realm.io that on logout, we totally destroy the realm cache that has been built up by the user so that when a new user logs in, we can recreate the cache file for the next user.
Deleting all objects is not an option as the realm file is encrypted using a hash of the users passcode so it has to be a fresh Realm (AFAIK).
Currently I am deleting the Realm file like so:
NSString *realmFile = [[DCMCacheManager documentsDirectoryPath] stringByAppendingPathComponent:#"myApp.realm"];
NSFileManager *localFileManager = [NSFileManager new];
[localFileManager removeItemAtPath:realmFile error:&error];
And reinstating it using:
RLMRealm * realm = [RLMRealm realmWithConfiguration:config error:&error];
When the creation code runs for the first time the realm file is created with no issues. When I try to recreate it after deleting, the app seems to return an internally cached version of the realm file so does not create the myApp.realm file for me.
Any suggestions on how to make sure the realm is absolutely dead when I delete it?
Before deleting the Realm file you will need to ensure that all Realm objects using that file have been deallocated. When possible, the easiest way to do this is to simply do the deletion before you ever open the Realm file at all, or if you only need the Realm to be open very briefly, to do so within an explicit autoreleasepool.
If users can log out and log into a different account while the app is running, then this isn't an option. Instead, what I would recommend is to use a different file path for each user (i.e. something like NSString *realmFile = [[DCMCacheManager documentsDirectoryPath] stringByAppendingPathComponent:userName]; rather than #"myapp.realm"). This would sidestep the issue entirely, and make switching back and forth between users faster. If your Realm files take up a nontrivial amount of space, you could clean up the files for all but the currently active user on app startup.
On a side note, if your Realm files are purely just a cache then Apple wants to you put the file in the Caches directory and not the Documents directory, and they do occasionally reject apps for not doing that.

How to correctly configure path for the Realm DB-file (<db_name>.realm) in iOS project?

Sorry for my english.
I have developed a mobile application that needs its own local data store. I chose Realm as the database management system. In the process of studying the Realm documentation I had no problems with the database design, it's normalization, the CRUD-operations and everything that is related directly to the code.
I was confused following. I test my application in the simulator. I did not create the local database. I’ve just done it as it is written in the documentation of Realm. Realm created by itself its database and I did not specify any settings. The location of my file with database is given below:
/Users/macbookpro/Library/Developer/CoreSimulator/Devices//EFECD945-285C-494F-8C1B-950D9AA05147/data/Containers/Data/Application/8D71FF0A-60D2-4875-96BB-36955E80D505/Documents/default.realm.
I quite inconvenient to apply each time this path for the analyzing of records in the database. The file is stored at this path is inaccessible for Realm Browser, because I need root privileges. I have seen that people store their .realm-files in project directory. Answer me please - how can I do it? Would it be the right alternative?
I have repeatedly seen the code, where paths to the database file appeared. For example, here: https://github.com/pietbrauer/CarthageRealmUploadFailureExample/blob/master/Carthage.checkout/realm-cocoa/examples/ios/swift/Migration/AppDelegate.swift
I'm not sure if it's the right direction.
As a result, I want to:
1) have on hand a database file and be able to quickly refer to it;
2) know the algorithm - how to set own path to the Realm-database
file;
3) know what realm configuration must be on a real device, to
ensure security and data integrity.
Thank you very much to all!
When you don't specify a path for the default Realm in your app, Realm will automatically create one named default.realm in the Documents directory of your app. On apps running in the iOS Simulator, this will save the Realm file in the appropriate Simulator folder, but you are correct in that it's not very intuitive to find it.
In response to your questions:
There is a cool utility called SimPholders that lets you inspect the Documents folders of apps in the iOS Simulator. This is the best way to get at any Realm files the Simulator has generated very quickly.
When creating an instance of a Realm object, you can supply a Configuration object to customise it. You can explicitly set the file path of the Realm file by setting the path property of that Configuration object.
iOS supplies an automatic layer of file encryption on disk, that makes files unable to be read when the device is locked. If you want additional security, then it's possible to set the encryptionKey property of a Realm Configuration object to have a Realm itself encrypt that Realm file on disk.
I hope that helped! Let me know if you need any more clarification!
1) and 2) does have very small effect on security and data integrity
3) if you are worry about security of you data, use Realm-level encryption like here

Unload Realm because of new database file

I am trying to update precompiled database in my app using a new database file downloaded from the internet. However when I download the file and replace the old one used by Realm with it, Realm still uses the old one till the next app restart. Unfortunately I still need to open the first DB to copy some data from it before downloading a new database. Is there a possiblity to force unload/reload the whole database?
I made a mistake and I accidentally created a new instance of Realm. The problem is that Realm instances are cached. I needed to use autoreleasepool {} and ensure that Realm is created only in the block.

Resources