.realm file automatically backed up by iCloud - ios

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)

Related

is the temporaryDirectory of FileManager automatically removed by iOS? if so when?

I am adding an option in my App to backup everything to a file.
For that, I am serializing all my objects to a dictionary that I save in a single file in the path provided by FileManager.default.temporaryDirectory. Then I ask the user for a path to save this file using a UIDocumentPickerViewController.
Everything works fine, but I wonder what happens with the temporal file that I created in the temporaryDirectory. Is this automatically removed by the operating system? should I take care of removing it by myself?
This is how I get the path of the temporary directory for my file:
private var exportURL: URL {
let documentURL = FileManager.default.temporaryDirectory
let fileName = "archive"
let filePath = "\(fileName).backup"
return documentURL.appendingPathComponent(filePath)
}

Saving Cache Files to Disk in iOS

I am working on an Application which deals with audio files. For this application, it is best not to stream the files, since you might download the files to your device and then disconnect from the server and listen to them later, perhaps in areas with no cell reception.
I created a caching system that stores the data to a file path and then stores the file location in CoreData with it's associated data.
self.name = name
var domainMask = UserDefaults.standard.string(forKey: "userDomainMask")
if domainMask == nil {
domainMask = NSSearchPathForDirectoriesInDomains(.cachesDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).first!
UserDefaults.standard.setValue(domainMask, forKey: "userDomainMask")
}
var cachePath = domainMask!
cachePath = (cachePath as NSString).appendingPathComponent(DataCache.cacheDirectoryPrefix + name)
self.cachePath = cachePath
ioQueue = DispatchQueue(label: DataCache.ioQueuePrefix + name)
self.fileManager = FileManager()
}
But when I try it on device, it is able to access the data at the file path, but it fails to load the file and play it.
The kicker is, when I share a file from my phone, it is able to find the file and upload it to the server, then retrieve it from the cache and display and play the file. If I re-run the application, it returns to a state where it can access the data, but the audio file does not load.

Monitor file with some kind of persistent id

My app writes files to the users shared Documents directory. I save the files path but this breaks if the user changes the documents name, moves the document to a new location etc. Is there some kind of persistent file id i can use to keep track of these documents?
i've been poking around
FileManager.default.attributesOfItem(atPath: docUrl.path)
and i find attributes like FileAttributeKey.systemFileNumber but this number seems to change every time i run the app. There has to be some way to keep track of files other than their path
You need to use url bookmarks, like the following (sketch)
if let bookmark = try? URL(fileURLWithPath: docUrl.path)
.bookmarkData(includingResourceValuesForKeys: nil,
relativeTo:nil) {
// store somewhere persistent bookmark to your file
}
...
let bookmark = // read bookmark from persisten storage
var stale = false
if let url = try? URL(resolvingBookmarkData:bookmark, bookmarkDataIsStale: &stale) {
// work with resolved url
} else {
// file disappeared - handle the situation
}

Swift - Realm mobile platform today extension

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.

How to find Apple App Group shared directory

We are currently developing an iOS10 app, including "Messages Extension".
To share CoreDatas persistant store.sqlite inbetween App and Extension, we are using a shared "Apple App Group" directory, which is working fine.
Now we have to get our hands on the store for debug reasons and are unable to find the directory. The Apps container directories are completely empty, which makes sense. But how to download our database? Do we have to somehow copy it programmatically to a reachable place?
To sum it up:
We already use CoreData which stores model.sqlite in our shared directory.
Everything is up and running.
What we want to archive is to download the database to our computer.
Without a shared directory we can simply download the App container from the device, using Xcode->Devices. But as we do use a shared directory, the .sqlite database is not within the container.
Question:
How can we download the .sqlite database from the device to our computer?
EDIT on 2018-10-12: Updated code for Swift 4.x (Xcode 10). (Older version retained for reference.)
In Swift 4.x:
let sharedContainerURL :URL? = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.etc.etc")
// replace "group.etc.etc" above with your App Group's identifier
NSLog("sharedContainerURL = \(String(describing: sharedContainerURL))")
if let sourceURL :URL = sharedContainerURL?.appendingPathComponent("store.sqlite") {
if let destinationURL :URL = FileManager().urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("copyOfStore.sqlite") {
try! FileManager().copyItem(at: sourceURL, to: destinationURL)
}
}
In older version of Swift (probably Swift 2.x):
let sharedContainerURL :NSURL? = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier("group.etc.etc") // replace "group.etc.etc" with your App Group's identifier
NSLog("sharedContainerURL = \(sharedContainerURL)")
if let sourceURL :NSURL = sharedContainerURL?.URLByAppendingPathComponent("store.sqlite")
{
if let destinationURL :NSURL = NSFileManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0].URLByAppendingPathComponent("copyOfStore.sqlite")
{
try! NSFileManager().copyItemAtURL(sourceURL, toURL: destinationURL)
}
}
Something like the above will get a file from the app group's shared container to the app's Documents directory. From there, you could use Xcode > Window > Devices to get it to your computer.
You could also use iTunes file sharing to retrieve the file from the app's Documents directory after setting UIFileSharingEnabled to YES in the Info.plist file, but bear in mind that this will expose the directory's contents to the user as well. Should be okay for development/debugging purposes, though.

Resources