App Updates, NSURL, and Documents Directory - ios

I have an app in the app store that uses Core Data to persist much of the data.
The exception is storing images. I store images in subdirectories to the Documents directory and store an NSURL reference to that image in the appropriate object attribute in the core data store.
We have noticed that, when an update makes it to the app store, those images are not found, and thus don't display, using the references stored with the previous version of the app.
Now, I have a suspicion that the problem is that, since we are using development devices for testing, this issue propagates because the Directory in the Applications directory to which the dev app uses differs from the one the App store is creating/using. I have noticed differences between the App store directory for the app in Applications and the one created while debugging versions in Xcode.
As such, the URL stored in core data points to the wrong applications folder.
This is kinda hard to debug, as I cannot download an older app version, once the new version has been released in the store.
So I have a couple questions. Can I guarantee that the Applications subdirectory in which folks who download versions of the same app will be the same, rendering this a non-issue for non-development devices?
Should I be storing relative image url's or strings to represent the location of these resources, or should I be fine with storing what ends up being the absolute urls?
Thanks so much,
Felipe

You should use relative URLs to store references to files. The absolute URL is likely to change after an app update
Files Saved During App Updates
When a user downloads an app update,
iTunes installs the update in a new app directory. It then moves the
user’s data files from the old installation over to the new app
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.
https://developer.apple.com/library/ios/#DOCUMENTATION/iPhone/Conceptual/iPhoneOSProgrammingGuide/PerformanceTuning/PerformanceTuning.html
Thx to the sandbox, the application home is also the user home. So it is possible to use the unix tilde which is a short hand to the user home, i.e. ~/Documents, ~/Library and so on.
Use -[NSString stringByAbbreviatingWithTildeInPath] to turn a full path into a relative ~ path. And reverse it with -[NSString stringByExpandingTildeInPath].

I think what you're looking for is the following:
NSString *appDocumentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

Related

What is the safest directory in iOS which can be used to download images/pdfs? [duplicate]

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

resolveLocalFileSystemURL on iOS using different App UUID each time

I am using Cordova fileSystem to download some mp3 Audio files thru my App. I am using cordova.file.cacheDirectory and creating a subfolder within that to store the downloaded files. However, the problem is that each time I make some changes and run the App on iPad I get a different path.
The usual pattern is
file:///var/mobile/Containers/Data/Application/13E9EA83-94A2-4950-811E-E491AC176‌​A78/Library/Caches/MyFolder/MyFiles.mp3
However the long number (App UUID) is not consistent. It changes each time I run the App on iPad through Xcode. Because of this I am unable to access, play, delete any files downloaded during the previous session because I am saving the file names with absolute path in a separate file for quick access in the future.
After some R&D I have realized that even though UUID changes each time, it actually refers to the same location. Hence the solution is not to save absolute path and instead, save only the Path beyond "/MyFolder/" in the above example. Each time when the App is run, the Base Path, which is actually file.cordova.cacheDirectory, should be appended to each entry to obtain the absolute Path to the file.

iOS Disk access based restore function

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.

Where to copy a readonly data file from bundle?

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.

Does updating iOS apps delete library directory files?

I keep save files in a private directory in my iPad app, namely the one returned when I use:
paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
documentsDirectory = [documentsDirectory stringByAppendingPathComponent:#"Private Documents"];
Notice that I also append a subdirectory to it. When I update the app, users are telling me that their progress in the app is getting destroyed. Are files in this NSLibraryDirectory destroyed every time I update the app? If so, should I be using NSDocumentDirectory instead?
Additionally, is there no way to make a further update to my app to remedy this without destroying all my my current users' save files? It doesn't seem like there is.
When a user downloads an app update, iTunes installs the update in a new app directory. It then moves the user’s data files from the old installation over to the new app 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.
This is provided by apple officially. See this link :
iOS Developer Library - File Saved During App Updates
I would also like to add this info as a personal experience with a big online game. You can't rely at 100% that your "Document" and "Library" folder will always be there. In fact, you can't rely that your app folder will still be at the same place on your device after an update.
Let me explain it a little bit more. When you install an app on your device, the real path will be /var/mobile/Applications/[some class id]/[your app].app/...
We're not sure who defines the class id of your app (either the iOS or app store), but this Id can change when updating the game resulting in having your app in a totaly different folder so your old files aren't there anymore. Our QA experienced it and our users too.
I won't go through the details on how we found that out and how we managed to get around this (private company stuff, usual shit...), but you need to consider it if you're doing an app that affects tons of users and might be updated a couple of times. It might have been fixed since, but it's always good to have a backup plan.
You should save them in the Documents folder, it is persistent across updates.
Monotouch: documentsDirectory = environment.specialfolder.personal;
Objective-C: NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)

Resources