In my iPhone app I'm caching the raw data of some compressed files to save loading time. But those files may change in an update.
Will iOS clear /Library/Caches for me when the app is updated or I need to clear it myself?
Short:
Will iOS clear /Library/Caches for me when the app is updated
No
Is it possible that iOS does clear everything or parts of Application_Home/Library/Caches during an update? Yes
or I need to clear it myself? You need to ensure what you want to be cleared is cleared.
Be prepared for both situations.
How do you know whether your app got updated? See iOS Application Update Test
Long:
Files Saved During Application Updates When a user downloads an
application update, iTunes installs the update in a new application
directory. It then moves the user’s data files from the old
installation over to the new application directory before deleting the
old installation. Files in the following directories are guaranteed to
be preserved during the update process:
Application_Home/Documents
Application_Home/Library
Although files in other user directories may also be moved over, you
should not rely on them being present after an update.
From Apples Documentation: The Application Runtime Environment - Backup and Restore
Application_Home/Library/Caches Use this directory to write any
application-specific support files that you want to persist between
launches of the application or during application updates. Your
application is generally responsible for adding and removing these
files. It should also be able to re-create these files as needed
because iTunes removes them during a full restoration of the device.
In iOS 2.2 and later, the contents of this directory are not backed up
by iTunes.
From Apples Documentation: The Application Runtime Environment - The File System (daveoncode)
Here an example of when it does clear the cache during an "update":
You install app X V1.0. Lunch it once and the start doing something else. iOS malfunctions and needs to be restored. Developer releases V1.1. You update the app in iTunes on your Mac. You restore your device via iTunes. iTunes installs V1.1. User lunches your app. Your app does not get notified that any of that stuff happened but all files in Application_Home/Library/Cache are gone (iTunes removes them during a full restoration of the device).
Really important information in there: It should also be able to re-create these files as needed. Like Kendall also pointed out it is a cache, so files could be deleted from it by the operating system at any point. So every time you load any file from Application_Home/Library/Caches you have to account for the case that the file isn't there anymore (Kendall touched on this).
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
if(![fileManager fileExistsAtPath:[cachePath stringByAppendingPathComponent:#"myfile.zip"]]) {
//create it, copy it from app bundle, download it etc.
}
//start using it
To be safe, you should clear it yourself. There does not seem to be any documentation stating that it will be cleared for you, so even if it does now you cannot count on it continuing to do so.
The caches directory will be purged if iOS is running out of space. If the user chooses "update all" from the app store options, it is likely that they will run out of space.
You should only store files in the Caches directory if they can be recreated by your app. From what I understand, the media player in iOS7 will only play videos stored in caches directory, and here's how I clear them manually (just in case):
-(void)deleteAllVideos
{
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSFileManager* fileManager = [NSFileManager defaultManager];
NSArray *directoryContent = [fileManager contentsOfDirectoryAtPath:cachePath error:NULL];
NSError* error;
NSString* fullFilePath = nil;
for(NSString* fileName in directoryContent)
{
if([fileName hasSuffix:#".mp4"])
{
fullFilePath = [cachePath stringByAppendingPathComponent:fileName];
[fileManager removeItemAtPath:fullFilePath error:&error];
if(error)
{
DLog(#"Error: %#",error);
}
}
}
}
It's up to you! Quote from Apple's documentation:
Use this directory to write any application-specific support files
that you want to persist between launches of the application or during
application updates. Your application is generally responsible for
adding and removing these files. It should also be able to re-create
these files as needed because iTunes removes them during a full
restoration of the device. In iOS 2.2 and later, the contents of this
directory are not backed up by iTunes.
The whole point of /Caches is that the system can clear data stored there at any time - if it needs to. You should not worry about clearing out that directory.
Related
I have a plist in my app that is already in appstore. Users can make saves/changes in that plist. It is stored in the apps Documents folder.
Will this plist remain if the users update to a new version, or is it returned to default (what is sent in the app bundle)?
Thanks in advance.
Your user-updated plist in Documents should be safe: data in the app bundle (such as the resource path) gets overwritten, but data in the user's Documents and Library folders isn't. This is why you can update apps and still have your documents and preferences intact.
Note that it's important to use the standard iOS calls to get the path to the Document's folder, not to (for example) hard-code the path.
See also:
iphone: preserve user data against app update
app data loss on version upgrade
It depends on how you coded the app... But if your app is set up to only load the plist into your bundle when there is not currently a plist than it shouldn't be over-written.
I had an update come out today and my plist data was still there...
This is how a plist should be copied into the bundle from your resources folder the first time the user launches the app: (*Note, if the user deletes the app then downloads the update the data will be gone)
if (![fileManager fileExistsAtPath: path]) {
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"YourPLIST" ofType:#"plist"];
[fileManager copyItemAtPath:bundle toPath: path error:&error];
}
Actually, My app got rejected from app store because i am storing about 9 MB data in document directory.
What is better and suitable location store image cache and to create sqlite database file?
The image cache has to go into the cache directory. A cache should not be included in a backup because you can recreate those images easily.
If the sqlite file stores user data you should put it into the document directory. It has to be included in device backups because you can't recreate it and the user would lose all his data when he restores his device from a backup.
If the sqlite file is downloaded from the web and it is never changed by the user put it into the cache directory too. On iOS 5.0.1 and later you could put that file into the documents directory and set the "Do not backup"-Attribute. However, on device with iOS 5.0 or earlier you HAVE to put that file in the caches directory.
NSString *cacheDirectory = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
The concern area is the iOS 5.0, which supports iCloud, but does not recognizes “do not backup” attribute. In this case, all the data of the app inside documents directory is likely to get backed up to iCloud. For the iOS versions below 5.x:
the iCloud backup is not valid.
the "do not back up" flag is not relevent. It would not produce any warnings during compilation.
Hence the data can be kept in the documents directory, with "do not back up" flag appropiately added to the contents (files/folders), for all the versions. The problem is for the version 5.0 only.
if you have lot of image in Your application.then sotre images in any image store site and use link of image. its better for You.
My iOS app was rejected because I use the /Document directory to store downloaded images.
I will move the downloaded images in the /Library/Caches directory to solve my problem.
But my sqLite database also contains elements manually created by the user.
This file must be copied into the /Library/Caches directory or /Documents directory to be accepted by the Reviewer ?
Sincerely,
Maxime
As per the iOS Storage Guidelines (which can be found at http://developer.apple.com/icloud/documentation/data-storage/) you should put all user-generated content in the Documents directory and all re-downloadable content in the Caches directory. So you should be fine putting the sqLite database there.
The background on this is that starting with iOS 5 the Documents directory is backed up to iCloud. As a lot of apps tend to store their complete data there the iCloud backups get rather large, which uses up the free space and creates network traffic, both of which in turn anger the user because he/she wonders why. To mitigate this Apple now seems to take a much closer look on what is saved into the Documents directory and if this is possibly regeneratable content (e.g. downloadable files).
Beware, that the Caches directory can and will be purged on iOS 5 by the operating system at times when the free space on the device gets low. Thus your app cannot longer just assume that everything is there as it was before but you rather have to re-check every time you access something out of your cache.
The data manually created can be stored with in your app directory.
You can use below code to get the current directory -
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
and then append you file name to get the full path.
NSString *fileName = [documentsDirectory stringByAppendingPathComponent:#"myfile.format"] ;
I've got an iPhone app under development that I plan on using for research purposes. As testers use the app on my development phone, it stores analytics data in a local database (right now SQLite, but I'm not opposed to migrating to CoreData).
After testing is done, I need to be able to copy this analytics database off of the phone onto my computer so I can run queries on the data. What is the easiest way to accomplish this? If necessary I'll iterate through the data, print it to the device log, and then import it back into a database on the desktop, but I'd like to find a way to just grab the .sqlite file without running it through an intermediary format.
You can use the Xcode Organizer to download a zipped snapshot of your app's Documents and Library directories from your device.
You can always try to print it to a PDF, using the UIKit is a simple way to export information and formating in a easy way, unless you think this method can't apply to your database ;)
Do you know if we can email the SQLite database directly from the iOS device?
Easiest way would be to add the UIFileSharingEnabled key (as a boolean, set to YES) to your Info.plist, then use something like this:
NSString *docsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
[[NSFileManager defaultManager] copyItemAtPath:whereverTheDatabaseIs toPath:[docsPath stringByAppendingPathComponent:#"exported.sqlite"] error:NULL];
Then, you or your users will be able to grab the database off the device using iTunes's file-handling malarkey.
edited - actually, see Ole's answer: I didn't know about that trick, and it'll probably be much faster.
Thanx ole begemann.
In organizer open your app and then Download that particular send Box. So It will create a .xcappdata extension file.
You can rename the extension to .zip then you will find the same folder as in InApp directory folder in your finder. and you can work with your data.
My iPhone app (well, idea of it) needs to do changes to iPhone's filesystem. Does iPhone API allow that?
Your app has its own piece of filesystem that you can read from and write to but you can't access anything outside that, ie you cannot access the filesystem areas of other apps or the OS itself.
Yes Cocoa Touch for iPhone OS allows file access. With the caveat that it naturally only allows file access for files that the current user has read-write permissions to access. Each application runs as single user, and really only have access to it's own small sandbox of files. So you will not be able to access system files, or files from another application.
There are two main directories that you might want your app to access:
NSDocumentDirectory - Analogous to you own Documents folder, the contents of this folder is backed up when you synch the device.
NSCachesDirectory - This one resides in /Library/Caches/ and is not backed up when synching the device.
You get the path to these directories using the NSSearchPathForDirectoriesInDomains function. When searching you will get an array of potential paths, it is safe to use the first path as long as you only search in the user domain. For example:
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString* docsPath = [paths objectAtIndex:0];
Once you have a path you can work away with your files using the default file manager. For example remove a file:
NSFileManager* fm = [NSFileManager defaultManager];
[fm removeItemAtPath:filePath error:NULL];
i just wrote a tutorial on how to do this using NSMutableArrays that you can check out that should help you. http://idevkit.com/iphonedev/2009/09/saving-nsmutablearrays/
if you have anymore questions on it lemme know and ill add to it