iOS Physical Memory Management (File Cache) - ios

I'm storing image files in Documents directory for file caching.
var paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
var path = paths.stringByAppendingPathComponent(imagePath!)
data.writeToFile(path, atomically: true)
What will happen when so many file stored? Is there auto swapping? Or can i detect it with code?
NOTE: I don't want to use tmp directory.

That's what i want. Thanks #gnasher729.
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.

There is no Auto Swipe mechanism to handle such task. It's user data and user should have control over it, when to write and when to delete. You can program such task within application. You need to decide if you want
1. To keep a check based upon no of days from file creation or
2. To keep a check on no of maximum files that are allowed within directory.
You can run this task in background every time while launching the application .
You can delete individual files using below code. Check this Question
[[NSFileManager defaultManager] removeItemAtPath: pathToFile error: &error];
Note - I recommend going through iOS Data Storage Guidelines to figure out which directory will suit you better

Related

How should we decide whether to use documentDirectory or applicationSupportDirectory?

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.

How can I get a non-expiring cache in iOS?

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.

iOS App Rejection due to 2.23 - Realm database

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

Caching hundreds of files on iOS app for 24-48 hours: all in Document folder or better in multiple folders?

If you need to cache hundreds of files on disk for an iOS app, is it prudent to store them all in the app's Document folder? (They will be cached then deleted after 24-48 hours.) Are there any drawbacks, e.g., searching for a given file is slower if the folder has too many files? Or should you store them in separate folders for performance reasons? What is considered best practice for iOS?
You probably don't want to store them in the Documents folder as these can be accessed via iTunes file sharing. You usually store them in a cache directory. You can access cache URL's by using
[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask].firstObject
Depending on if these files shouldn't be deleted by iOS if the system is running out of storage space you might want to use the Library directory instead of caches by passing NSLibraryDirectory into the method above instead of NSCachesDirectory
see https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html for a more detailed explanation of the different storage types on iOS

Why is daltoniam Skeets proposing NSDocumentDirectory as location for cache files

In the documentation of Skeets, an image loader / cache framework written in swift for iOS / MacOS, one example shows how to specify the cache path.
//set the cache directory. Only have to do this once since `sharedManager` is a singleton
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
ImageManager.sharedManager.cache.diskDirectory = "\(paths[0])/ImageCache"
My understanding until now was, that the Document Directory (and its subdirectories) is NOT the right choice to store cache data, it even leads to failing the app review process, due to the fact, that the Document Directory gets backed up to the iCloud and cache data is nothing, which we really want to back up in the cloud.
Unless of course we exclude the Directory, which we specified, from the iCloud backup explicitly.
I thought the NSSearchPathDirectory.CachesDirectory would be the appropriate location to store cache data?

Resources