I'm using Cache framework for caching in my application. Cache framework can provide hybrid storage with expire option. I've set .never for both storages (disk and memory), but cache still can expire.
In my app i need to cache some Data() for forever, and update it if necessary (but not frequently). Speed of getting this cache is not that necessary.
Is it possible using this framework? May i need to use just DiskStorage, instead of Storage? I think it can expire, because it saving into system memory (which is RAM as i think) all the time, so iOS can clean it if needed, but can iOS clean disk storage?
So, i've found something about this in Apple Guidelines:
Use the "do not back up" attribute for specifying files that should
remain on device, even in low storage situations. Use this attribute
with data that can be recreated but needs to persist even in low
storage situations for proper functioning of your app or because
customers expect it to be available during offline use. This attribute
works on marked files regardless of what directory they are in,
including the Documents directory. These files will not be purged and
will not be included in the user's iCloud or iTunes backup. Because
these files do use on-device storage space, your app is responsible
for monitoring and purging these files periodically.
I wrote simple function for this:
func setExludedFromBackup() {
var url = try? FileManager.default.url(
for: .documentDirectory,
in: .userDomainMask,
appropriateFor: nil,
create: true).appendingPathComponent("MyFolder")
var resuorceValues = URLResourceValues()
resuorceValues.isExcludedFromBackup = true
try? url?.setResourceValues(resuorceValues)
// print(try? url?.resourceValues(forKeys: [.isExcludedFromBackupKey]).isExcludedFromBackup)
// you can check if your directory excluded from backup (it excluded if "Optional(Optional(true))" printed)
}
Yes, it's Documents folder, because other folders still continue to be cleared.
You simply call this func somewhere (i've used AppDelegate), and check if directory is already excluded from backup before calling it. That protect "MyFolder" in Documents directory from deleting, if iOS has ran out of memory! So my data will be available as long as i want to. But you must include after-time deleting mechanism too, because this data will never be deleted automatically and on-device memory space will not be released. In my case i just used Cache framework's expiry property
P.S. Im not sure how will Apple react to this, while inspecting your app for AppStore, so tell them about offline use in your app and what you did with documents folder, don't forget to describe your deleting mechanism. I hope that doesn't break Apple Guidelines and app will not be rejected.
Related
We plan to store the following user files
SQLite file
Image files
Audio files
We also provide an option for users, to upload and download the above files, to a 3rd party cloud storage.
I was wondering, should we use
FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
or
FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
for the above file storage purpose?
Historically we used the “Documents” folder, but nowadays the “Application Support” directory is the best place for files like this.
The File System Programming Guide says
Put user data in Documents/. User data generally includes any files you might want to expose to the user—anything you might want the user to create, import, delete or edit. For a drawing app, user data includes any graphic files the user might create. For a text editor, it includes the text files. Video and audio apps may even include files that the user has downloaded to watch or listen to later.
Put app-created support files in the Library/Application support/ directory. In general, this directory includes files that the app uses to run but that should remain hidden from the user. This directory can also include data files, configuration files, templates and modified versions of resources loaded from the app bundle.
Remember that files in Documents/ and Application Support/ are backed up by default. You can exclude files from the backup by calling -[NSURL setResourceValue:forKey:error:] using the NSURLIsExcludedFromBackupKey key. Any file that can be re-created or downloaded must be excluded from the backup. This is particularly important for large media files. If your application downloads video or audio files, make sure they are not included in the backup.
Put temporary data in the tmp/ directory. Temporary data comprises any data that you do not need to persist for an extended period of time. Remember to delete those files when you are done with them so that they do not continue to consume space on the user’s device. The system will periodically purge these files when your app is not running; therefore, you cannot rely on these files persisting after your app terminates.
Put data cache files in the Library/Caches/ directory. Cache data can be used for any data that needs to persist longer than temporary data, but not as long as a support file. Generally speaking, the application does not require cache data to operate properly, but it can use cache data to improve performance. Examples of cache data include (but are not limited to) database cache files and transient, downloadable content. Note that the system may delete the Caches/ directory to free up disk space, so your app must be able to re-create or download these files as needed.
Also see the iOS Storage Best Practices video.
If using the .applicationSupportDirectory, I’d suggest you use url(for:in:appropriateFor:create:) with create set to true:
let folderURL = try! FileManager.default
.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
It doesn't make much difference which you choose. The chief difference is in case you want to use a file browser or the Files app; they can look in your documents directory but not in your application support directory.
Also if you pick one and release the app and later change your mind, it's easy to migrate and change where the app stores its information.
Currently i was saving my application data (Media) to the CacheDirectory i.e
/var/mobile/Applications/BEAFC76C-C450-4A3A-9765-A0385A9580F3/Library/Caches
and things were going fine. But recently i got a bug report that the application data has been deleted. When i searched over it, i got this Apple Doc. According to it, DocumentsDirectory should be the ideal place to store the User/Application data.
Put user data in the /Documents/. User data is any
data that cannot be recreated by your app, such as user documents and
other user-generated content.
And Cache should not be used to store the User Data that could not be reproduced by the application.
Put data cache files in the /Library/Caches
directory. Examples of files you should put in this directory include
(but are not limited to) database cache files and downloadable
content, such as that used by magazine, newspaper, and map apps. Your
app should be able to gracefully handle situations where cached data
is deleted by the system to free up disk space.
What should be the ideal place to store it.
EDIT:
I have an application that allows user to store Videos and Photos in the application. For that i used CacheDirectory. But i am getting bug reports that the Data (Videos/Photos) is getting deleted. What conclusion i draw is that the data is being getting delete by the Device itself in order to provide space.
Secondly i also wanna give the iTunes sharing function. So only the particular files has to be stored in the DocumentsDirectory. Some files can never be exposed and some has has to be shared. What should be the ideal way to store the files.
Use Documents (NSDocumentDirectory) for files you wish to share via iTunes.
Use Application Support (NSApplicationSupportDirectory) for files you wish to hide from the user but still be backed up and never deleted by the OS.
Starting iOS 5, Apple says that it's no longer a good thing to save all kind of files in Documents Directory - if you do that, your app will be rejected for sure because this folder is backed up to iTunes & iCloud, unless otherwise specified.
It says that we should save files into Caches or Tmp Directory - these won't be backed up, but it's not a good thing to do because files from these directories can disappear if low memory happens.
So I think the best think to do is to save the important files that you need all the time in your app into Documents Directory and mark them not to be backed up, like this.
Library/Application Support Folder is the folder you should be using.
This directory doesn't always exist, and thus you may need to create it.
You can enable or disable whether you want to backup this data with iTunes or not.
This data is not accessible even if you enable file sharing. Only data that you put in Document directory would be shared with iTunes sharing, so you can still protect your data and get it backed up as well. Apple's documentation
Here's message from Apple:
2.23 Details
On launch and content download, your app stores 6.38 MB on the user's iCloud, which does not comply with the iOS Data Storage Guidelines.
Next Steps
Please verify that only the content that the user creates using your app, e.g., documents, new files, edits, etc. is backed up by iCloud as required by the iOS Data Storage Guidelines. Also, check that any temporary files used by your app are only stored in the /tmp directory; please remember to remove or delete the files stored in this location when it is determined they are no longer needed.
Data that can be recreated but must persist for proper functioning of your app - or because users expect it to be available for offline use - should be marked with the "do not back up" attribute. For NSURL objects, add the NSURLIsExcludedFromBackupKey attribute to prevent the corresponding file from being backed up. For CFURLRef objects, use the corresponding kCRUFLIsExcludedFromBackupKey attribute.
I checked my testing device iCloud backup and it is about ~0,3KB on launch.
I am using Realm.io database for storing data, but I set path of realm file to ..Library/Cache. Realm version 0.100.
change of path in code:
Realm.Configuration.defaultConfiguration.fileURL = NSURL(fileURLWithPath: NSSearchPathForDirectoriesInDomains(.CachesDirectory, .UserDomainMask, true)[0].stringByAppendingPathComponent("cache.realm"))
So I checked storage activity in debugger and also placement of file. But every option shows that files are actually saved in Cache folder and Documents folder is empty. Am I missing something ? What should I do next ?
Looks like you're writing something to the documents directory. What makes you think Realm is responsible writing to the user's documents? Are you perhaps using an image cacheing library which writes to the documents directory?
If you're certain that the documents directory is empty, why is Apple telling you otherwise?
If you access the Realm prior to overwriting Realm's default configuration, then it's possible you're actually writing to the documents directory until that time.
If you somehow confirm that Realm is writing to a different directory that you've specified, please file a bug report at https://github.com/realm/realm-cocoa/issues/new
I am trying to code a hard disk based restore function into an existing demo Photo Application for iOS devices. The idea is to allow users to restore the last applied effects and all, even after restarting the application/unexpected crash etc.
I am saving one image file (the latest effects applied to it) into the NSCachesDirectory:
NSData* data = UIImagePNGRepresentation(image);
[data writeToFile:[self getFileAtIndex:getPath] atomically:YES];
On going to the recover option, the file saved at this path is recovered using:
image = [[UIImage imageWithContentsOfFile:[self getFileAtIndex:getPath]]retain];
The code is working fine in my test device (iPhone 4s). But somehow I doubt if this is the best practice for coding a restore function.
Moving into a real world app, if things were stored in NSCachesDirectory, do you think it will be backed up into iCloud? Is there any possibility of a conflict with other apps?
How exactly is NSCachesDirectory directory managed for multiple apps accessing it simultaneously?
I would like to know the best practice for doing this.
Please help/comment.
As Mr. Bonjour mentioned in the comment, on iOS, every app has its separate file system, so there can never be any conflict with other apps.
Caches directory is not backed up on iCloud and you shouldn't rely on files in caches directory to persist across launches. You should use caches directory for temporary files only. If you allow restore only during one session, then using caches directory is fine, but if you want to allow restore across multiple launches, you should store them in library/documents directory. But be aware that Apple has a strict review policy for storing files in Documents directory since it takes up space on user's cloud storage.
I'm a bit confused. I'm including in the bundle a Core Data file that will not be modified by the user. Apple rejected my app after I started copying the file to /Documents (due to the new iCloud requirements), so I now I copy the file over to /Library/myprivatedir/
The question is why do I need to copy over to /Library in the first place. What's wrong with it staying in the Bundle after all?
There's nothing wrong with opening a CoreData store from within the bundle. Just be sure to pass the NSReadOnlyPersistentStoreOption as part of the options to -addPersistentStoreWithType:configuration:URL:options:error:
Skimming the docs for iOS Data Storage Guidelines (apple id required) I found this
... Data that can be downloaded again or regenerated should be stored in the <Application_Home>/Library/Caches directory. Examples of files you should put in the Caches directory include database cache files and downloadable content, such as that used by magazine, newspaper, and map applications.
Because it is easily regenerated they may have taken issue with it.
A couple of points down may be useful if you did have a read/write database scenario
... Use the "do not back up" attribute for specifying files that should remain on device, even in low storage situations. Use this attribute with data that can be recreated but needs to persist even in low storage situations for proper functioning of your app or because customers expect it to be available during offline use. This attribute works on marked files regardless of what directory they are in, including the Documents directory. These files will not be purged and will not be included in the user's iCloud or iTunes backup. Because these files do use on-device storage space, your app is responsible for monitoring and purging these files periodically.