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.
Related
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.
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.
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.
My iOS app uses CoreData and some tables need to be filled with default values every first time the app is opened since CoreData device-dependent.
So I am using NSUserDefaults to check whether it is first time open. If it is first time, I fill tables (on CoreData) with the values which I have already created and formatted lines from the txt file by reading line by line and separating in a way.
And my question is, is it safe and fastest way to use txt file for such operation?
A better option would be to keep a "canned" sqlite file in your app bundle and check for the existence of the SQLite file in your documents directory. If the file does not exist, copy the canned data from the app bundle to your documents directory.
That will skip the entire parsing logic and will allow your application to launch faster.
Marcus' approach is also what I would recommend. But you can still keep using your parsing code during development in order to have a convenient way to create the seed SQLite file. When you ship your app, package the newest seed store as a bundle resource and disable / delete your parsing code.
I would like to make backup copies of my app's main sqlite DB while my app is running.
1) I have read that it is safe to just copy the sqlite file if the DB has been checkpointed (at that point the wal file contains no important data). Does [managedContext save:] do that checkpointing, or is there something else I have to do? (ref -shm and -wal files in SQLite DB)
2) Is there any way, short of tearing down the whole core data stack, to be sure that core data doesn't try to write to the sqlite file while I'm copying it? My app does save frequently after any user input, and it would be nice if there was some way to force that to block for a second.
I have uploaded a sample app that provides backup and restore capabilities a number of different ways, including local backups, copy backups to and from iCloud, email backups, import from email, and file copy via iTunes. See link below for video demonstrating these capabilities and you can download the sample apps from the site.
http://ossh.com.au/design-and-technology/software-development/sample-library-style-ios-core-data-app-with-icloud-integration/sample-apps-explanations/backup-files/
EDIT
It should be safe to create a new persistentStoreCoordinator with the same fileURL and to then use migratePersistentStore API without closing the App, save the main MOC first though. I always use JOURNAL=DELETE mode to ensure I just have to use a single file to deal with. If you are using WAL mode then you would need to backup all three files used by sqlite.
Regarding 2)
When I make backup, I close all mom's, moc's and persistent store. Then it's safe to make backup or restore. Also all views are waiting for events to release all coredata resources and bring them back when database is available again. It's good to have a singleton to manage coredata.