Change Realm file without restarting application - ios

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.

Related

Replace Realm file while app is running

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.

iOS 10+ using NSPersistentContainer - What's the best method to "clear all"

We want to have a settings bundle property that can be set to delete all the information stored using core data. I see some examples that loop over all the entities and calls delete. I see some that manipulate the files storing the stores. This last way sounds better but I'm not sure how that fits into the magic of NSPersistentContainer.
On iOS 10, what's the best way to delete all the content in Core Data and continue on in the app saving new fetched data to Core Data?
I haven't tried it, but here's what I think I'd do:
Create a new directory where you'll keep your persistent store and anything else that NSPersistentContainer wants to save. Make sure to create this directory when the app launches, using FileManager. You'll use this with Core Data by...
Subclassing NSPersistentContainer and overriding defaultDirectoryURL(). Use the directory from step 1.
Now you'll be sure that everything the persistent container writes goes in a known location that doesn't contain anything else.
When you want to delete everything, just delete every file in the directory that you're using (again, using FileManager). Make sure to do this before loading any data.

Keeping a bundled realm up to date using REST

I have an app that uses a database of about 5000 entries.
This database is bundled in the app as a realm file.
I want to be able to update/add entries to this database regulary using REST and I think I have done it correctly - I just want to make sure.
This is how I have done it:
When the app is installed I copy the bundled database from the mainBundle to the Documents directory for read/write access. I then delete the database from the mainBundle.
When I update/add new entries to the database, they are pushed to the user using REST and inserted into the database located in the Documents directory.
When an update is released of the app, I make a check to see if the database already exists in the Documents folder - if it does I automatically remove the database in the mainBundle as it is not needed.
Am I on the right track with this? Is there a better way of doing it?
Appreciate any input!
Regards,
Erik
When I update/add new entries to the database, they are pushed to the user using REST and inserted into the database located in the Documents directory.
Technically, you can't push via REST. So I guess, you're either sending a background push notification to all installations or you're checking at application launch, whether there is a new version of the database available. That's at least what I would propose, but your requirements for getting new data out may vary.
When an update is released of the app, I make a check to see if the database already exists in the Documents folder - if it does I automatically remove the database in the mainBundle as it is not needed.
This doesn't work. The main bundle is the signed app bundle. If you would tamper the contents, that would prevent your app from launching. For that reason the access to it is limited by the OS to read-only. So this operation will always fail with an error. Instead you might properly just want to skip seeding the database from the main bundle.

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.

Migrating coreData to a clean start

I'm updating an app to a whole new version (remade). Everything is going to change to be faster and less bugy. As other post suggest I cannot create another version of the model since I don't have the app code to the previous version (I started a new project). All I have is the bundle identifier for it to be an update. I will use core data but I want to delete all the old models and old data for the users that are updating, as if they deleted the app and reinstall it. How do I achieve this? or there's no need to delete anything because is a different model? All i want is to prevent app crash on launch. thanks in advance.
If you tried to open the same persistent store file with a model that doesn't allow Core Data to make sense of it then you'd raise an exception. So probably all you need to do is use a different file — remember that you get to specify the on-disk location in addPersistentStoreWithType:configuration:URL:options:error: — for your persistent store and ask NSFileManager to delete the old one.
I don't think there's a penalty for asking to delete a file that already doesn't exist so no need for any particularly complicated logic. You'd just be duplicating what the file manager does internally anyway.
Alternatively, if you prefer to keep the same file, enclose your call to addPersistentStoreWithType:... in an #try/#catch block and in the #catch just delete the existing file and try the addPersistentStoreWithType:... a second time.

Resources