saoudrizwan / Disk

Delightful framework for iOS to easily persist structs, images, and data

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Persist sharedContainer file even in low storage situations

adrianod1as opened this issue · comments

Hi,

First, great work! Second, I have a realm database file, which I would like to share with app extensions and also persist it even in low storage situations. Currently the data is being purged because of low space.

I have not found any mention about it yet, but do you know if will the method .doNotBackup work on such files?

I am currently using
let path = "\(getDatabaseName()).realm"
let fileURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: group)!.appendingPathComponent(caminho)
let configuration = Realm.Configuration(fileURL: fileURL, encryptionKey: getKey() as Data)
configuration.deleteRealmIfMigrationNeeded = true
let realm = try Realm(configuration: configuration)
do { try Disk.doNotBackup(path, in: .sharedContainer(appGroupName: group))
} catch let error as NSError { debugPrint(error.localizedDescription) }`

None error is thrown, however I am not sure if this will work since you have mentioned this method only for .documents and . applicationSupport , or if it is even the best approach (suggestions?).

It is in my plans to implement a check where I prevent the user from using the app, or at least warn him, if the available space is too low using Disk.availableCapacity. Nevertheless, are there other implications besides prevention from being backed up by iCloud or iTunes? Anything I should be worried, I mean.

Hey Adriano, thanks for the kind words!

Yes, if you use the .doNotBackup(:in:) function on your Realm database file, then it will not be purged in low storage situations, but like you said it will also not be backed up by iCloud/iTunes, which may not be worth it.

The .doNotBackup(:in:) method is kind of hard to wrap your head around, but I'll try my best to explain it. In the iOS file system, you can set file properties (AKA resource values) for any object your write to disk. This set of properties is either stored alongside the object in a hidden "cache", or it's stored in an app/global cache (AKA backing store) depending on a ton of factors like capacity, optimization, etc. (stuff Apple takes care of in their private APIs.)
You can set these "cached file properties" (AKA URL resource values) using the setResourceValues(_ values: URLResourceValues) function.
Disk uses this function to set a 'do not backup' or 'do back up' file property (resource value) whenever you call the .doNotBackup(:in:) and .backup(:in:) functions on a file.
Now if you look into the documentation for setting resource values, you'll find that:

Attempts to set a read-only resource property or to set a resource property not supported by the resource are ignored and are not considered errors. (Source)

I haven't tested if a file stored in a shared container is allowed to have its 'do not backup' file property set, so this method may possibly be failing without throwing an error. What you should do is to first make sure that the Realm database file is properly stored by retrieving it's file system URL using Disk.getURL(for:in:) and then check if that file has the property 'do back up even in low storage situations' cached with it using resourceValues(forKeys keys: [URLResourceKey])
Let me know what you find out!

In any case, the best practice here though is to:

  1. Check if the user has enough storage to store the Realm database file.
  2. If he doesn't, notify him that he can't use your app until enough space is freed up.
  3. Save your Realm database file in the shared container.
  4. Make sure this Realm database file exists in the expected location.

Now repeat these steps every time you try to add data to the Realm database file. I don't recommend you use the .doNotBackup(:in:) function unless you're absolutely certain that it's more important for all your users to be able to access the database file in low storage situations than for that database file to be backed up by iCloud in case the user loses his phone, changes phones, etc.

Let me know if you need any more clarification, I'd be glad to help!

@saoudrizwan

First, I really appreciate the thoughtful explanation, and as a feedback, I've been using your lib as I first stated, and none occurrences were reported since then. So thank you very much, and keep up the good work. o/