Moving data from bundle to user doc folder not responding accurately - ios

I have an app that has several in app purchases in it and it also includes one free mp3 when the get the app in the first place and we have the list of mp3 they can play from when purchased and if they want to stream it and we also have a saved session section where they can move it offline and still be able to listen to it only here they can loop and do other things that would incur huge data costs.
The process goes like this I load the mp3 into the bundle and then upon opening the saved sessions view it checks to see if this file exists there if it doesn't then it copies it from the bundle location to the sandbox loacation and then proceeds normally so if it wiped out it will automatically recover itself from the bundle location.
The problem is this it wont't reload at all until at least one other file has been saved no matter what I do actvity wise in the app it just won't move that track in from the bundle UNTIL another track gets moved in first and I restart the app then the next time I go in I notice the slight delay of about a second and it is there in all its glory so I know I am close but I can't figure out why it won't initially do it.
Maybe someone out here can see what I ma missing it was late when I wrote the code so I will go for that as an excuse anyway here is the snippet of code I am working with
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *dataPath = [docDir stringByAppendingPathComponent:#"Sessions"];
NSFileManager *filemgr = [NSFileManager defaultManager];
NSString *freeMp3FilePath = [dataPath stringByAppendingPathComponent:FREEMP3];
// Check if the file already exists
DLog(#"%#",freeMp3FilePath);
if (![filemgr fileExistsAtPath: freeMp3FilePath]){
DLog(#"File Not Found");
NSString *freeMP3Address = [[NSBundle mainBundle] pathForResource:#"m-app_0129instantconfidencehd" ofType:#"mp3"];
if([filemgr copyItemAtPath:freeMP3Address toPath:freeMp3FilePath error:nil]) {
DLog(#"File Copied");
} else {
DLog(#"File Not Copied %# %#",freeMp3FilePath,freeMP3Address);
}
}
In the log I see the "File Not Found" message and then I see the "File Not Copied" and the two paths do show up and look just as expected as seen here
2013-06-06 10:37:00.092 IMOB[51674:907] <SavedViewController.m:(57)> File Not Found
2013-06-06 10:37:00.097 IMOB[51674:907] <SavedViewController.m:(62)> File Not Copied /var/mobile/Applications/6D5463FF-4106-479A-8E77-16BD24B22CCF/Documents/Sessions/m-app_0129xxxhd.mp3 /var/mobile/Applications/6D5463FF-4106-479A-8E77-16BD24B22CCF/IMOB.app/m-app_0129xxxhd.mp3
This entry show nothings is in the directory and this also is the case if I shut down the app and restart it
2013-06-06 10:37:00.113 IMOB[51674:907] <SavedViewController.m:(169)> CURRENT ICON ARRAY COUNT :0
Ok hopefully this is something easy
Jeff

You should have added the error parameter when copying the file and checked what it contained...
Before you copy the file, ensure the destination directory exists using createDirectoryAtPath:withIntermediateDirectories:attributes:error:.

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];

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!

Has the Core Data database persistent storage location changed

I was getting the persistent storage error that has been reported by many others. However in my case it was not due to changing the database model. I chased that rabbit for a couple of hours. Finally one post lead me to try and delete the database itself. I went to the directory my URL pointed to
url=/Users/ccox/Library/Application Support/iPhone Simulator/7.1/Applications/8A231E05-B3A2-4E83-8C81-6B3989C262A5/Library/Documentation/DBEViewDocumentand
it didn't exist.
url=/Users/ccox/Library/Application Support/iPhone Simulator/7.1/Applications/8A231E05-B3A2-4E83-8C81-6B3989C262A5/Library/
was there but the Documentation directory was not there.
Here is the code I am using to get the URL
NSFileManager *fileManager = [NSFileManager defaultManager];
NSURL *documentsDirectory =[[fileManager URLsForDirectory:NSDocumentationDirectory inDomains:NSUserDomainMask] firstObject];
NSString *documentName = #"DBEViewDocument";
self.url = [documentsDirectory URLByAppendingPathComponent:documentName];
self.document = [[UIManagedDocument alloc] initWithFileURL:self.url];
NSLog(#"url=%#",[self.url path]);
The output from the NSLog is the output URL above.
Is there a setting somewhere that sets the destination location for that documents directory? Apparently the Documentation directory is a not a standard directory since it's not created as part of the application install.
I went ahead and created the Documentation directory and now everything is working fine (at least that far), but I can't believe this is by design and that everyone is having to do this.
Any thoughts?
Thanks
Chip
You're using the wrong directory. NSDocumentationDirectory is not a standard location for documents, and is not created by default. You want NSDocumentDirectory, which is created by default.

How to hardcode a text file into iOS app

Currently using:
NSString* path = [[NSBundle mainBundle] pathForResource:#"filename"
ofType:#"txt"];
This only works however after I manually add the file into the application bundle.
I can use the documents directory but that's even worse.
After resetting the sim, the file goes away. How do I get it to stay?
How would I write out the file from somewhere to there? Like from a file in source? I don't want to alloc a several megabyte NSString object.
Credit goes to Lyle42 on freenode irc (#iphonedev):
I wasn't aware this field even existed. By adding any file into the copy files build phase (under build phases), they persist across builds.
Then this code:
NSString *_filePath = [[NSBundle mainBundle] pathForResource:#"filename" ofType:#"txt"];
NSLog(#"%#",_filePath);
NSData *_binary = [NSData dataWithContentsOfFile:_filePath];
NSString *_fileContents = [[NSString alloc] initWithData:_binary encoding:NSUTF8StringEncoding];
Works just great. (loads contents of file into an NSString).
You can use this to get your path for the file
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [documentPaths objectAtIndex:0];
filePath = [path stringByAppendingPathComponent:file_name];
you can get the file from your app bundle using
NSString *pathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:file_name];
I can use the documents directory but that's even worse.
Not really. The documents directory is persistent, and the recommended directory for essential documents created by your application. In addition, it's backed up by iTunes, and can be specified for iCloud backup. The app bundle just can't compete with that!
After resetting the sim, the file goes away. How do I get it to stay?
You can't, once the simulator has been "reset" (and I mean a hard wipe of all data and apps), nothing is saved. In between test builds, however, data copied out of the app bundle should survive unless you're storing things in /tmp. In addition, objects in the bundle are "refreshed" (recopied) in the build phase, meaning your resource isn't wiped out, merely reset to the one specified in your project.
How would I write out the file from somewhere to there? Like from a
file in source? I don't want to alloc a several megabyte NSString
object.
To read the file into memory, it would have to turn into a "several megabyte NSString" eventually, but if you really want to add a little IO to your plans for a massive string object, have a look at NSFileManager.

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