While updating the Application all local files are deleted in iPhone - ios

In my application I have saved videos and photos in document directory and photos and videos url path store in sqlite. While updating (Upgrading) the iPhone Application all document directory photos and videos are deleted. But other parameters stored in sqlite not deleted. How to I retain the files while updating the app?
-(BOOL)saveImageToDocumentDirectory:(UIImage*)imgToBeSaved
{
BOOL flag = NO;
strPhotourl=nil;
NSData* imgData = UIImageJPEGRepresentation(imgToBeSaved, 1.0);
// NSData *imgData1=UIImagePNGRepresentation(imgToBeSaved);
// Create a new UUID
CFUUIDRef uuidObj = CFUUIDCreate(nil);
// Get the string representation of the UUID
NSString *strImageName = (__bridge NSString*)CFUUIDCreateString(nil, uuidObj);
CFRelease(uuidObj);
//Call Function to save image to document directory
NSArray* arrAllDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* strDocumentDirectory = [arrAllDirectories objectAtIndex:0];
NSFileManager* fileManager = [NSFileManager defaultManager];
NSString *fullPath = [strDocumentDirectory stringByAppendingPathComponent:[strImageName stringByAppendingString:#".png"]];
strPhotourl=fullPath ;// strPhotourl store in sqlite db table two show images in tableview
// NSLog(#"Image in strphotolocation==%#",imagePath);
// NSLog(#"fullpath---%#",fullPath);
if(![fileManager fileExistsAtPath:fullPath])
flag = [fileManager createFileAtPath:fullPath contents:imgData attributes:nil];
else
flag = NO;
return flag;
}

The reason is not because any files were deleted but because the folder an iOS app resides in does change during an upgrade. The folder your app is stored in is named using a GUID, and this may change on an upgrade.
You should not store the full URL/PATH to any files in your Documents folder, as this is not guaranteed to remain after an upgrade.
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
If you already have the app deployed on users phones, then what you could do is when you read the url from sqlite, remove the leading path (eg: /var/mobile/Applications/---guid---/Documents) and then re-save the entry before using it.

Don't save the entire path into sqlite,just save the file name which you are stored in local so while fetching, get the current directory path and append with fileName from sqlite. This will solve when you upgrading your app also.

Related

Writing big file on IOS [duplicate]

I save some run-time generated files inside the .app bundle of my iOS app. In the simulator it works fine, in the device it crashes:
Could create output files in the given shader cache path
'/var/mobile/Applications/CB064997-B40E-4FE3-9834-B3217CE33489/SimedTest.app/Ogre3D/assets/RTShaderLib/cache/
Is there a good overview of where I should and shouldn't put files - how to use Documents, Library and tmp, etc?
To clarify, these are files created at startup which pre-calculate some data to save time. IF they are not present they get created so it's fine they are deleted, but not while the app is running.
The bundle is read-only. You don't want to mess around with it for two reasons:
Code Signing: the signature is verified by against the contents of the bundle; if you mess around with the bundle, you break the signature.
App Updates: updates work by replacing the entire app bundle with a newly downloaded one; any changes you make will get lost.
Where you should save stuff:
Documents: if you want it to persist and be backed up
Library/Caches: if you just want to cache downloaded data, like profile pics; will be auto deleted by the system if it is low on room unless you specify with a special do-not-delete flag.
tmp: temporary files, deleted when your app is not running
For a full explanation check out File System Programming Guide and QA1719.
No, every time you change your bundle you invalidate your signature.
If you want to write files you`l need to write in the best folder depending on what you want to do with that file.
Documents folder for long duration files
Cache for small operations
and so on
EDIT
To get the path you`ll need something like this:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"filename.ext"];
With this path you can write or read like this:
write:
NSString *content = #"One\nTwo\nThree\nFour\nFive";
[content writeToFile:fileName atomically:NO encoding:NSStringEncodingConversionAllowLossy error:nil];
read:
NSString *content = [[NSString alloc] initWithContentsOfFile:fileName usedEncoding:nil error:nil];

Large files downloaded to Documents and backed up to iCloud

I have an iOS app in the app store that can download relatively large files that need to stay on the device for offline use. Those files are currently stored in the app's Documents folder but I'm just now reading that the Documents folder is backed up and should really only be used for user-generated content. This Apple technical Q&A states that the NSURLIsExcludedFromBackupKey should be set to prevent backup. This states that an app's /Library/Caches is the right place to put these kinds of files although further reading suggests that the folder may be cleared when the device is low on storage which is unacceptable for this app. I believe /Library/Application Support/ is then the best location for them -- does this sound right?
Unfortunately, this mistake got through the app review process. What are some best practices for fixing this now that people are using the app and already have some files persisted to the Documents folder and to their backups? It seems I need to move all the existing files and set their NSURLIsExcludedFromBackupKey on app update. How do I guarantee that this is done exactly once and that it isn't interrupted? Is moving the files out of the Documents folder important or could I leave them there? Will changing the files' backup status remove them from existing backups?
I'm using Swift 2.1.1 and targeting iOS 8.0+.
As stated in the technical Q&A, you best bet could be create a subdirectory in the Documents, and exclude that subdirectory once.
I don't believe you can write a 'do it once and be sure it is done' routine, since you can't guarantee your app doesn't crash while it is running. You certainly could set a completion flag when you are sure it is done so that once it is done you don't have to run it again.
Exclude your directory from backup, not the individual files.
From Xcode:
You can use this property to exclude cache and other app support files which are not needed in a backup. Some operations commonly made to user documents cause this property to be reset to false; consequently, do not use this property on user documents.
Here is the strategy I have used with good results
(sorry, its in objective-c -- I'm not a swift guy. Hopefully it will give you the idea):
- (BOOL)moveAllFiles{
// Searches through the documents directory for all files ending in .data
BOOL success = true;
NSString *myNewLocation = #"/store/my/files/here/now";
// Get the documents directory
NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [documentDirectories objectAtIndex:0];
// Get all files ending in .data (whatever your file type is)
NSArray *dataFilesArray = [NSArray arrayWithArray:[NSBundle pathsForResourcesOfType:#"data" inDirectory:documentDirectory]];
// If you have multiple resource types, use this line once each for each resource type, then append the arrays.
// Iterate the found files
NSString *fileName = [NSString string];
for (int i=0; i<[dataFilesArray count]; i++) {
fileName = [[dataFilesArray objectAtIndex:i] lastPathComponent];
// Move file, set success to false if unsuccessful move
if (![[NSFileManager defaultManager] moveItemAtPath:[dataFilesArray objectAtIndex:i]
toPath:[myNewLocation stringByAppendingPathComponent:fileName]
error:nil]) {
success = false; // Something went wrong
}
}
return success;
}
Now use the value of success to set a key in the user defaults file. Check for that key on startup. If it is false (or absent), run this routine (again).
This example is with file paths. You can do the same thing with file URLs if you wish.

iOS - Reading an Audio file from Documents Directory

I am saving audio data to the Documents directory and trying to read it back. If I play it back immediately it plays successfully, however, if I start a new session and try and play the song locally it will fail even though listing the files in the Documents directory shows that my file is still there. Note that the file is played back from the Documents folder in the same way (same code) if it is played immediately or during a new session.
Here is how I save the audio data to the Documents directory:
+(void)writeDataToAudioFile:(NSData*)data forTrack:(MediaItem*)track
{
// filename looks like "[track_id].mp3"
NSString *fileName = [NSString stringWithFormat:#"%#.%#",track.sc_id,track.original_format];
NSString *pathName = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask,
YES) firstObject]
stringByAppendingPathComponent:fileName];
[[NSFileManager defaultManager] createFileAtPath:pathName
contents:data
attributes:nil];
}
Then in my music player I want to load the local URL to this file to initialize the AVPlayer:
NSURL *url;
if(_currentTrack.is_local_item)
{
url = [NSURL fileURLWithPath:_currentTrack.local_file_path];
}
url does not get created properly as AVPlayer does not play. Furthermore, I have tried every different way to load the file as data into an NSData object to check the byte size but trying to access the file as data always returns nil. However, the file exists as if I use NSFileManager I am able to iterate over the items in the Documents directory and print their file names/paths, validating that I the path I have saved in "_currentTrack.local_file_path" does exist. Again, if I play the file immediately after saving the file to disk it will play back.
If there is more info I can provide to make this clearer I will. Thank you very much.
Do not write the full directory path to DB. It will change. You need to only save the file name to DB as reference. Then use as follows:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *fileName = #"SAVED_FILE_NAME.mp3"; // eg: [track_id].mp3
NSString *filePath = [documentsPath stringByAppendingPathComponent:fileName];
This will provide you the actual path of the file.
Keep coding........... :)
I found the solution after putting the problem down for a few days. I break-pointed and print-stated the heck out of the program and I found that the file path I was saving was not the same as the file path of the file.
I think this was a simulator issue, as the issue only occurred between different sessions of the simulator, and worked within the same session, so the device id (which is part of the absolute path) was changing - maybe someone more knowledgeable can weigh in on that.
Pay closer attention to the string values of your variables folks!

What happens to files stored in the documents directory when an app is updated?

I couldn't find the answer to this anywhere but I am saving various files in my app to the documents directory using archiving. If I release an update for the app and the user installs it what happens to these files? Will they be deleted?
code to get to documents:
//get the directory
NSArray *documentDirectories = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//set it to a string
NSString *documentDirectory = [documentDirectories firstObject];
return [documentDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#stickers.archive",[PFUser currentUser].username]];
No, the files will remain.
You can then go ahead and change them as part of the update or just use them like before.
But you should be careful how you reference the saved files, since they will be in a new directory after the update: App Updates, NSURL, and Documents Directory Basically you should only save the relative path from the documents directory, that will remain unchanged as well.

Does an iOS app have write access inside its bundle?

I save some run-time generated files inside the .app bundle of my iOS app. In the simulator it works fine, in the device it crashes:
Could create output files in the given shader cache path
'/var/mobile/Applications/CB064997-B40E-4FE3-9834-B3217CE33489/SimedTest.app/Ogre3D/assets/RTShaderLib/cache/
Is there a good overview of where I should and shouldn't put files - how to use Documents, Library and tmp, etc?
To clarify, these are files created at startup which pre-calculate some data to save time. IF they are not present they get created so it's fine they are deleted, but not while the app is running.
The bundle is read-only. You don't want to mess around with it for two reasons:
Code Signing: the signature is verified by against the contents of the bundle; if you mess around with the bundle, you break the signature.
App Updates: updates work by replacing the entire app bundle with a newly downloaded one; any changes you make will get lost.
Where you should save stuff:
Documents: if you want it to persist and be backed up
Library/Caches: if you just want to cache downloaded data, like profile pics; will be auto deleted by the system if it is low on room unless you specify with a special do-not-delete flag.
tmp: temporary files, deleted when your app is not running
For a full explanation check out File System Programming Guide and QA1719.
No, every time you change your bundle you invalidate your signature.
If you want to write files you`l need to write in the best folder depending on what you want to do with that file.
Documents folder for long duration files
Cache for small operations
and so on
EDIT
To get the path you`ll need something like this:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"filename.ext"];
With this path you can write or read like this:
write:
NSString *content = #"One\nTwo\nThree\nFour\nFive";
[content writeToFile:fileName atomically:NO encoding:NSStringEncodingConversionAllowLossy error:nil];
read:
NSString *content = [[NSString alloc] initWithContentsOfFile:fileName usedEncoding:nil error:nil];

Resources