I saved some data with Realm on my iPhone, and in AppDelegate, I wrote
var config = Realm.Configuration()
let container = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.XXXXXXXX")
let realmUrl = container!.appendingPathComponent("default.realm")
config.fileURL = realmUrl
Realm.Configuration.defaultConfiguration = config
Also, in ExtensionDelegate, I wrote the same.
But when I tried to access data from watch, it shows nothing.
I printed the URL and found that iPhone saves data in
"Developer/CoreSimulator/Devices/21B1330F-3B9D-4A45-9EE4-0D06F9A48866/data/Containers/Shared/AppGroup/3697965E-9A56-447E-B0EB-BC1722DB0BD0/default.realm"
But the watch saves in
"Developer/CoreSimulator/Devices/B190D8C9-A6D8-4BE1-AD8D-7D2805BFA739/data/Containers/Shared/AppGroup/3E621FF7-86FA-4C49-9AC1-20C6C198CB2F/default.realm"
I'm now wondering how to access Realm data saved in my phone from my watch
Now solved by transfering the whole realm file with WatchConnectivity
Related
Just to be clear, its currently not possible to use Realm to have a single shared database between an iOS app and a Messages extension?
It is very much possible
For Swift 3
I used the following code to share Realm db between app and app extension:
let sharedDirectory: URL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.your.app")! as URL
let sharedRealmURL = sharedDirectory.appendingPathComponent("db.realm")
Realm.Configuration.defaultConfiguration = Realm.Configuration(fileURL: sharedRealmURL)
Just call this code from didFinishLaunchingWithOptions of AppDelegate and viewDidLoad of MSMessagesAppViewController
I used this configuration code for local storage.
var configuration = Realm.Configuration.defaultConfiguration
configuration.encryptionKey = getKey() as Data
I used this configuration code for sync with server.
let syncServerURL = URL(string: serverUrl + objectName!)!
var configuration = Realm.Configuration.defaultConfiguration
configuration.encryptionKey = getKey() as Data configuration.syncConfiguration = SyncConfiguration(user: SyncUser.current!, realmURL: syncServerURL)
I create some data without sync, it is saved locally. However, if I turn on sync(different configuration), the previously created data(locally) is not synced to the server? How to sync already saved data?
Realms are uniquely referenced by one of three mutually exclusive Realm.Configuration properties:
fileURL
inMemoryIdentifier
syncConfiguration
Realm configurations with any of these properties with different values will refer to separate Realms.
So your initial Realm has a fileURL value (with nil for the other two properties), whereas your second Realm has a syncConfiguration value (with nil for the other two properties) so they refer to separate Realms.
If you wish to copy data from the first (local) Realm to the second (synced) Realm, you may do so using Realm's APIs for reading objects & creating objects just like you would for any other data.
I'm building a Notes app with today extension.
I want to link my app's data with today widget using App Group.
To do this, I have to change the default realm's fileURL to App Group URL.
Without syncConfiguration it works very well, but when I use this, the default realm's fileURL did not changed.
So my Questions is how can I change Realm.Configuration.defaultConfiguration.fileURL using realm mobile platform!!!
let file = FileManager.default
let directory: NSURL = file.containerURL(forSecurityApplicationGroupIdentifier: "group.com.myapp")! as NSURL
let realmPath = directory.appendingPathComponent("default.realm")
Realm.Configuration.defaultConfiguration = Realm.Configuration(
fileURL: realmPath,
syncConfiguration: SyncConfiguration(
user: user,
realmURL: URL(string: "realm://myserver:9080/~/myNote")!
),
objectTypes: [realmNote.self, Tag.self]
)
self.realm = try! Realm()
please help!!!...
If you set a sync configuration on the Configuration object, you cannot set a custom file URL. The sync configuration, file URL, and in-memory identifier are mutually exclusive settings. This is by design.
If you need it to work otherwise, please feel free to file a ticket at our GitHub repository, and we'll take a look.
I have an iPhone (iOS 8) and Apple Watch (watchOS 1) apps that share their data using Core Data (SQLite store, placed in shared app group). Both apps are using the same data access code that is placed in shared framework. NSPersistentStoreCoordinator is being set up in the following way:
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
let sharedContainerURL = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier(self.sharedAppGroup)!
let storeURL = sharedContainerURL.URLByAppendingPathComponent(self.databaseName)
let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
var error: NSError? = nil
if coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: nil, error: &error) == nil {
fatalError("Unable to add persistent store: \(error)")
}
return coordinator
}()
From my understanding, in runtime each app has its own NSPersistenStoreCoordinator instance (as iPhone apps and WatchKit extensions do have completely separate address space), but these two connect to exactly the same SQLite database file.
How can an iPhone app be notified when Watch app changes some data in the common SQLite store and the other way around: how can a Watch app be notified when the iPhone app changes some data in the common persistent store?
The solution that I've found quite satisfactory was to use MMWormhole library.
It works by using CFNotificationCenter Darwin Notifications and writing/reading data files in the shared app group, which results in instant communication between an iOS app and an app extension (Watch app, today's widget, etc).
Basic code goes like this:
Wormhole initialization
wormhole = MMWormhole(applicationGroupIdentifier: appGroup, optionalDirectory: nil)
Passing data object to a wormhole
let payload = ["Key": "Value"]
wormhole.passMessageObject(payload, identifier: theSameMessageIdentifier)
Listening for incoming object from a wormhole
wormhole.listenForMessageWithIdentifier(theSameMessageIdentifier) { message -> Void in
if let payloadDictionary = message as? Dictionary<String, String> {
// Do some work
}
}
It's as simple as that.
Not easily. There is no way to send a direct communication between the two applications.
My current recommendation in this regard is to use files on disk that include the objectIDs of anything that has changed from one app to the other.
When you detect a save to disk you write a file that, for example, is JSON and includes up to three arrays: update, insert, delete. The file name should be some form of timestamp.
Separately you should be watching the directory for any files created by the other app and consume them. Load the ObjectIDs and then create a notification out of the ala iCloud or in iOS 9 a remote notification. Then delete the file after process.
On launch, remove all files from the other store since you will automatically be aware of anything that happened pre-launch.
Not simple but fairly straight forward.
my app was rejected because of the size of the content that it uploads to iCloud. The only file in my app's Documents folder is the default.realm database file. I think that this is the file that iCloud is uploading. How can I prevent iCloud to upload the database to iCloud?
Thanks.
According to the App Backup Best Practices section of the iOS App Programming Guide, <Application_Data>/Library/Caches or <Application_Data>/tmp will not backup to iCloud. Generally, you can use <Application_Data>/Library/Caches directory to save your data that you won't backup to iCloud.
To change the file path of Realm, you can pass the path parameter when creating Realm instance, like below:
let realmPath = NSSearchPathForDirectoriesInDomains(.CachesDirectory, .UserDomainMask, true)[0] as! String
let realm = Realm(path: realmPath.stringByAppendingPathComponent("data.realm"))
Otherwise, you can use NSURLIsExcludedFromBackupKey file system property to exclude files and directories from backups (See Technical Q&A QA1719). If you want to use the default path, there is the only way to exclude Realm file from backups.
let realm = Realm()
if let realmPathURL = NSURL(fileURLWithPath: realm.path) {
realmPathURL.setResourceValue(NSNumber(bool: true), forKey: NSURLIsExcludedFromBackupKey, error: nil)
}
Looks like the URL API has changed since the previous answer was posted. This is how you can disable the backup now:
let realm = try! Realm()
guard var url = realm.configuration.fileURL else {
return
}
var resourceValues = URLResourceValues()
resourceValues.isExcludedFromBackup = true
try? url.setResourceValues(resourceValues)