How do I get my pre-populated Default.realm file onto a device? - ios

I have a realm file that is already populated with data that needs to be there when the app is loaded on a device.
What can I do to get the realm file onto my device for testing and what do I need to do to make sure it is already there when someone downloads the app from the app store?
I am using Swift.

Add your database file to the Xcode project, i.e. "preloaded.realm"
Make sure you select the add to targets, when first dropping in your file
Then (taking from the migration example) you can do something like this to copy that preloaded file to your default directory. This will create a read/write realm
// copy over old data files for migration
let defaultPath = RLMRealm.defaultRealmPath()
let defaultParentPath = defaultPath.stringByDeletingLastPathComponent
let v0Path = NSBundle.mainBundle().resourcePath!.stringByAppendingPathComponent("preloaded.realm")
NSFileManager.defaultManager().removeItemAtPath(defaultPath, error: nil)
NSFileManager.defaultManager().copyItemAtPath(v0Path, toPath: defaultPath, error: nil)
Here is a link to that general code https://github.com/realm/realm-cocoa/blob/master/examples/ios/swift-2.2/Migration/AppDelegate.swift

You'll first have to create the realm file you want to ship with your app. Once you have that, add it to your app's Xcode project and copy it into the bundle (which Xcode should do automatically).
At this point, the app should be able to access the bundled file (you can use NSBundle.mainBundle().pathForResource(_:ofType:) to get the path).
You can either create a read-only realm at this path (see RLMRealm(path:readOnly:error:)), or copy it to your Documents directory to create a read-write realm file.
You should refer to our migration example for more details on how to do this.

Related

Default value in core data

I have core data file generated by my app. This file contains a data. But I don't want this file generate in every user device. I want put this file in app and every user uses this file. How can I do this?
I have find answer here:
https://gist.github.com/xavierchia/ef43abb270003ae63e5bbb7eb5404645
I need just copy my SQL files to project and copy them in app directory.

Unable to Locate Realm File on Device

I am attempting to locate the realm DB file on my device (iPhone) and I followed the steps here and here. However, I do not see any realm files in the folder AppData/Documents.
I print out the URL path as I run the app on my device and my simulator, and this is what I see:
//On device
/private/var/mobile/Containers/Shared/AppGroup/C7332EE4-1567-4C96-8392-7FBD0DC9C863/DB/default.realm
//On simulator
/Users/MYNAME/Library/Developer/CoreSimulator/Devices/D205C50D-F432-4A1F-80CB-FB3D91E0A1EA/data/Containers/Shared/AppGroup/5E67A740-A338-4583-9B9D-461F5D1A734A/DB/default.realm
The URL written on the simulator appears to be any default URL where the Realm DB is written to. I can't seem to understand why can't I find the realm file at AppData/Documents on the actual device.
Realm files are only created on disk when you call Realm() for the first time. Once you've created an instance of Realm, you can find the exact file route of that Realm by printing out realm.configuration.fileURL. You can normally use Realm.Configuration to set a different location of the Realm file on disk as opposed to the Documents directory.
Both of those file paths you displayed show that the file is located in a folder named DB and it appears to be in an app group (eg, a shared folder between apps and extensions) instead of your app's default Documents directory.
So with that being said, it would appear that somewhere in your app, a custom Realm.Configuration object is being used to create the Realm file somewhere else, which would explain why you can't find it in Documents.

iCloud Drive cannot remove file created from other device

I'm trying to adopt iCloud Drive to store backups of the data of my application using a single file for each backup, if it's relevant they're simple XML files with a custom extension. File creation and upload are working fine but as I'm now trying to let the user manually delete backups I found out that I cannot delete the file programmatically but I can do it if I go to iCloud Drive from the app on iOS or the folder in Finder on macOS.
To save the files I first retrieve the root for the container with
FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents")
and create the Document folder if it doesn't exists as I want the user to be able to view and edit the files, after creating the file locally in the temporary directory I upload it with
let file = FileManager.default
if file.fileExists(atPath: remotePath.path) {
try? file.removeItem(at: remotePath)
}
try? file.setUbiquitous(true, itemAt: localPath, destinationURL: remotePath)
where remotePath is the path retrieved before with the file name appended. To load the files I use a NSMetadataQuery and get the path of each file with NSMetadataItemURLKey on each returned item, which is working fine but when I attempt to
try? FileManager.default.removeItem(at: retrievedPath)
it works if the same device created the file but if it is from another one it always fail and the error says that the file does not exists at the specified path.
I've removed error handling code for clarity but I've tested this behaviour inspecting the thrown error.
How can I delete any file even from other devices, am I missing some steps?
I was indeed missing something, after reading this question, in particular this answer, I found out that even if the NSMetadataQuery returns the path correctly is possible that the file has not been downloaded to the the device, hence the error.
To correctly delete a file you have to mimic the behaviour of UIDocument and use a NSFileCoordinator on a background queue, refer to the answer referenced before for implementation details.

What different between store database in different locations in iOS?

I'm working with SQLite.swift.
In the document, the path to the database is:
let path = NSSearchPathForDirectoriesInDomains(
.DocumentDirectory, .UserDomainMask, true
).first!
but i want to import and use an existing database, so i've dragged my existing database to my keyboard extension folder, and create connection to it with path is:
let path = NSBundle.mainBundle().pathForResource("db", ofType:"sqlite3")
So, i've noticed that the first way, the database will be store in /Users/*/Library/Developer/CoreSimulator/Devices/8B1DB861-AA3F-446F-A559-D4727CDB9285/data/Containers/Data/PluginKitPlugin/0BC647E4-26F3-4A1F-8271-CC73C96FD197/Documents
and the second way, the database will be store in the app.
/Users/*/Library/Developer/CoreSimulator/Devices/8B1DB861-AA3F-446F-A559-D4727CDB9285/data/Containers/Bundle/Application/E5D9514C-859A-4D4D-A771-A8CE9CDCD3E7/AppName.app/PlugIns/AppNameExt.appex
What's different between these two locations?
The second way might increase the app size because it contains the database?
And if i want to Archive/Submit my App to the AppStore with existing database, is this the only way?
The main difference is that storing the file in the documents folder means you can write (update) it, which is pretty important for a database file. You cannot write to a file in the app bundle.
The usual pattern for using a database in an app is:
Create a pre-seeded database during development and copy it to the app bundle during building.
When running, check if the database file exists and is up-to-date in the documents folder.
If not, copy it from the app bundle.
Open the database in the documents folder and read/write as desired.

Sqlite file copy while launching Application

How to store database from one sqlite file (which is in our bundle) to sqlite file (which is created while we using core data) while we launching application first time.
Should we copy each entity, each row in loop or Is there any other way to do this.
You can put sqlite file directly in your bundle, for example you can create sqlite file with SQLite manager in firefox. Then when start your app you can check if file exist in the document directory, if not you need to create it. This only the first time.

Resources