Document Directory in iPod Touch and iPhone - objective-c

I'm designing an application that reads data to the iPod touch/iPhone that is sent to it via multicast sockets with UDP and I need to store it as a file in a document directory. Does that exist on on the iPhone or iPod Touch? I know there is NSFileHandle and NSFileManager, which is what I plan on using, to take care of reading and writing to the file, but I'm not sure where the "My Documents" section of the iPod touch is if you know what I'm saying. I am not familiar with the iPod/iPhone file directory that well yet, so any help is appreciated! Is there some kind of "general" directory that all developers use to store their files in if they have any involved in their application?

You should use your application's Documents directory to store persistent files. You can get the path to the directory using this function, which Apple includes in their template for an application using Core Data:
/**
Returns the path to the application's documents directory.
*/
- (NSString *)applicationDocumentsDirectory {
NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *basePath = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;
return basePath;
}

More recently, the template for a Core Data application provides code like this:
- (NSString *)applicationDocumentsDirectory {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
If the returned NSArray from NSSearchPathForDirectoriesInDomains is empty, lastObject returns nil, so as a result, the code is shorter and cleaner.
One thing you should be aware of -- as of iOS 5, you shouldn't put non-user-generated-data to Documents directory. Your app may be rejected. Instead you should think of putting such logs in Caches directory. To get path of this one, you need to replace NSDocumentDirectory with NSCachesDirectory in the above example code.

Related

Multiple music file in document directory in iOS device

I am developing an application in iPhone .This application need to store 3 music file (.mp3) to iOS device (the files are from a webserver). The downloading function working perfectly (Using ASIHTTPrRequest). Some time the music saving not working perfectly, that means I am using a checking before the music file go to music player.
playpath=#"/Users/company/Library/Application Support/iPhone Simulator/5.0/Applications/3D5AD723-F18E-4F44-B3CB-FAEF2EA4963B/Documents/329/25-06-2012/330217/work25-06-2012330217.mp3"
NSFileManager*fileM=[NSFileManager defaultManager];
if([fileM isReadableFileAtPath:playpath])
{
}
The playpath (directory path) change with each downloading. some time the downloading paths playing the music and some time this not playing ie this path can not satisfied the above condition .
My questions are
What is reason for the above problem?
What is the exact functionality of isReadableFileAtPath?
Instead of explicitly writing out the file path, have the device find the path for you. Here's what I do:
- (NSString*) saveFilePath: (NSString *) add
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
NSString *filename = [path stringByAppendingPathComponent:add];
return filename;
}
Add this to whatever class needs to save or load data. Then you'll be able to get the location of your file with:
[self saveFilePath:#"Name of file you want to load or write to"]

path and directories in iOS

So I have the following method to get a path:
- (NSString *)filePath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *filePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:#"%#_json", self.identifier]];
return filePath;
}
this path will be used for a keychain access kSecAttrAccount and kSecAttrGeneric. So therefore I am expecting it to have the same path. However it turns out that after I upgrade my app this path changes.
Before it was:
/var/mobile/Applications/CEE344F7-4FE1-4455-BD6D-A4D6EAA4F5FE/Documents
and after wards it was:
/var/mobile/Applications/A6429F46-972C-4BC1-A71B-2786312663E8/Documents/
What can cause this to happen?
That means that iOS installs the updated version of the app in a new folder. Once that is done it will move the user data over to the new folder and remove the old one. This is probably done, so an error during installation won't corrupt the existing app.

Preloading Documents into iOS App

The Situation:
I have an iOS app that deals with files and lets the user save, edit, open and perform various operations with these files. I'd like to be able to have some pre-made documents for the user to look at when they open the app (ex. a template) alongside their own custom documents.
The Problem:
How can I create a document (or template file) and have it appear in the Documents folder after the user installs my app and launches it (and all preceding times)?
Background:
This document (the one that'd be installed into the app's documents directory) is created by me, not the user.
I know that to do this you need to save it in your bundle, and then when your app runs for the first time silently copy it into the Documents Directory. Should I copy it in the appDidFinishLaunchingWithOptions method or in my viewDidLoad method and write logic to detect if it's the first time the app has run?
My Code:
At this webpage: http://textsnip.com/d35fbc    
But when it runs, it always says: "File does not exist [in documents folder]", then it tells me that it's being copied. The problem is that when I examine the app's documents folder it is never there, it's still in the bundle.
Why won't it copy with this code
How does this work?
the files must in fact be added to the app bundle, then copied silently when the app launches.
The following code copies a text file from the top level of my bundle to the documents directory if it doesn't already exist.
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *txtPath = [documentsDirectory stringByAppendingPathComponent:#"txtFile.txt"];
if ([fileManager fileExistsAtPath:txtPath] == NO) {
NSString *resourcePath = [[NSBundle mainBundle] pathForResource:#"txtFile" ofType:#"txt"];
[fileManager copyItemAtPath:resourcePath toPath:txtPath error:&error];
}
The only flaw in this code is that if the user deletes the file, it immediately reappears when they open the app again.
As you said, you include it in your app bundle (add it to your project and make sure it's part of your target). Then you can access it's path by calling something like this:
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:#"MyTemplateDoc"
ofType:#"extension"];
Then you copy it to your app's documents folder.
NSString *docPath = <a path in your documents folder>
NSError *error = nil;
[[NSFileManager defaultManager] copyItemAtPath:bundlePath
toPath:docPath
error:&error];
if (error) {
// handle copy error.
}

Cydia App Documents Folder Not Created

I have been working on a Core Data iOS app that works perfectly through Apple's "channels" – iOS simulator & Xcode installing, yet when I try to manually install it onto a device, the application crashes. My main goal is to put the app on Cydia.
A guide to preparing an app for Cydia
I read this article, and I at the bottom it said
Appstore app has a Documents folder that is created by the installation process. Jailbroken app does not. It is up to the app to create its own folder. Should you need this type of folder, you must create this with a simple mkdir command in your applicationDidFinishLaunching function. Just add a simple function: mkdir(“/var/mobile/Library/YOURAPPNAME”, 0755); If the folder already exists, no harm done. You want to do this because the install process runs as user root and the app runs as user mobile. If Cydia does this for you then the folder will have the incorrect permissions.
I do not know much about how exactly Core Data works, but I know the Core Data "database" is stored in the Documents folder, and I now believe this is the cause of the crash of my app.
The mkdir function did not work in creating a Documents folder.
How would I go about creating a Documents folder, and how would I get it to work with Core Data, ensuring the database is loaded from this folder I created?
Thanks in advance
Most likely you are still using the AppStore friendly Documents path in the methods which create and load the CoreData database file (I think Xcode will put these in your AppDelegate by default).
Check the method which loads the persistentStorageCoordinator and look for a line like this:
NSURL *storeUrl = [NSURL fileURLWithPath: [docPath stringByAppendingPathComponent:#"my_cool_app.sqlite"]];
And make sure that docPath is "/var/mobile/Library/My_Cool_App" and not originating from the standard AppStore friendly:
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [documentPaths objectAtIndex:0];
You might want to create a method which returns the proper Documents directory depending on what target you compile the app for:
+(NSString *)documentsDirectoryPath
{
#ifdef JAILBREAK
NSString *documentPath = #"/var/mobile/Library/My_Cool_App";
if (![[NSFileManager defaultManager] fileExistsAtPath:documentPath])
{
[[NSFileManager defaultManager] createDirectoryAtPath:documentPath
withIntermediateDirectories:NO
attributes:nil
error:NULL];
}
return documentPath;
#else
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
return [documentPaths objectAtIndex:0];
#endif
}

File write with [NSBundle mainBundle] fails

I am trying to take content from one file and write it into another. I am reading fine, but I am not able to write it into another file.
I have a database of words. I want to separate the words into different files based on the number of letters. All four letter words go into one file, and so on. I added a txt file called "4letter" into my resources and the following is my code:
NSError *error;
//READ
NSString *dbFile = [[NSBundle mainBundle] pathForResource:#"words" ofType:#"txt"];
NSString *test = [NSString stringWithContentsOfFile:dbFile encoding:NSUTF8StringEncoding error:&error];
//convert from string to array
NSArray *lines = [test componentsSeparatedByString:#"\n"];
NSFileHandle *logFile = nil;
logFile = [NSFileHandle fileHandleForWritingAtPath:[[NSBundle mainBundle] pathForResource:#"4letter" ofType:#"txt"]];
//Test if write works
for (int i=0; i<5; i++)
{
NSString *randomAnagram = [[lines objectAtIndex:i] lowercaseString];
[logFile writeData: [randomAnagram dataUsingEncoding: NSNEXTSTEPStringEncoding]];
}
In iOS, you can't write into a file in your app's bundle -- the entire bundle is read-only. Use a path into the Documents folder instead.
See special File System Programming Guide for better understnading.
In iOS, you can't write into a file in your app's bundle -- the entire bundle is read-only.
Consider reading iOS Data Storage Guidelines to better understand the purpose of directories below, in context of iCloud backup.
<Application_Home>/AppName.app
This is the bundle directory containing the app itself. Do not write
anything to this directory. To prevent tampering, the bundle directory
is signed at installation time. Writing to this directory changes the
signature and prevents your app from launching again.
<Application_Home>/Documents/
Use this directory to store critical user documents and app data
files. Critical data is any data that cannot be recreated by your app,
such as user-generated content. The contents of this directory can be
made available to the user through file sharing. The contents of this
directory are backed up by iTunes.
<Application_Home>/Library/
This directory is the top-level directory for files that are not user
data files. You typically put files in one of several standard
subdirectories but you can also create custom subdirectories for files
you want backed up but not exposed to the user. You should not use
this directory for user data files. The contents of this directory
(with the exception of the Caches subdirectory) are backed up by
iTunes. For additional information about the Library directory, see
“The Library Directory Stores App-Specific Files.”
See full list (tmp/, Documents/Inbox) in iOS Standard Directories: Where Files Reside
UPDATE
I use NSFileManager method URLForDirectory:inDomain:appropriateForURL:create:error:
Like Caleb said, you can't write to your app's directory, but you can write to your app's Documents folder. You can get it like this:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
Your app's bundle is read-only. There is two ways I could see:
1) Write in documents folder:
NSArray *pathList = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path =  [myPathList  objectAtIndex:0];
2) Use sqlite database. This is the same as 1 (you must save db in documents anyway), but you're using sqlite database. I think this is better than a lot of txt and plist files: here's a tutorial on the topic.
I use the following code :
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:#"set.txt"];
NSString *data=#"Kostas";
[data writeToFile:appFile atomically:YES];
NSString *myData = [NSString stringWithContentsOfFile:appFile];
NSLog(#"Data : %# ",myData);