Hi I'm practicing with plists and I learned that there are 2 different ways to load them
FIRST METHOD:
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documents = [path lastObject];
NSString *filePath = [documents stringByAppendingPathComponent:#"test.plist"];
self.array = [NSArray arrayWithContentsOfFile:filePath];
SECOND METHOD:
NSString *filePath = [[NSBundle mainBundle]pathForResource:#"Ingredients" ofType:#"plist"];
self.array = [NSArray arrayWithContentsOfFile:filePath];
I don't understand clearly which way it's best... but I noticed that if I use the second one, I can't write in the plist. can anyone tell me more about it? which is the best and correct way? What's the difference?
i'm doing some tests and i have some code working only with one method...
//using this code the nslog will print null
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *filePath = [documentsPath stringByAppendingPathComponent:#"Ingredients.plist"];
ingredients = [NSMutableArray arrayWithContentsOfFile:filePath];
NSLog(#"ingredients:%#", self.ingredients);
//using this code the nslog will print the content of the array
NSString *filePath = [[NSBundle mainBundle]pathForResource:#"Ingredients" ofType:#"plist"];
ingredients = [NSMutableArray arrayWithContentsOfFile:filePath];
NSLog(#"Authors:%#", self.ingredients);
First Method
Your app only (on a non-jailbroken device) runs in a "sandboxed" environment. This means that it can only access files and directories within its own contents. For example Documents and Library.
Reference iOS Application Programming Guide.
To access the Documents directory of your applications sandbox, you can use the following:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
This Documents directory allows you to store files and subdirectories your app creates or may need.
To access files in the Library directory of your apps sandbox use (in place of pathsabove):
[NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]
Second Method
The Second Method is used to write the file in the Apps main bundle.
The main bundle is the bundle that contains the code and resources for the running application. If you are an application developer, this is the most commonly used bundle. The main bundle is also the easiest to retrieve because it does not require you to provide any information.
It is better to copy the file from App Main Bundle to App Document Directory and then use the document directories path to read/write file.
If you are using the first method you need to copy the file from your main resources to the Documents Directory.
Code to Copy file from app bundle to App's Document Directory
#define FILE_NAME #"sample.plist"
// Function to create a writable copy of the bundled file in the application Documents directory.
- (void)createCopyOfFileIfNeeded {
// First, test for existence.
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:FILE_NAME];
success = [fileManager fileExistsAtPath:filePath];
if (success){
return;
}
// The writable file does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:FILE_NAME];
success = [fileManager copyItemAtPath:defaultDBPath toPath:filePath error:&error];
if (!success) {
NSAssert1(0, #"Failed to create writable file with message '%#'.", [error localizedDescription]);
}
}
Sample Code Dropbox Link
Related
I dont know about how to open NSFileManager.
How to open NSFileManager in iPhone and upload document from NSFileManager please suggest any easy way.
How can open it and upload the document and also get the path for saved file.
Where I can find file physically.(Any location).
::EDIT::
I started coding in that year. so, i don't know about basic of NSFileManager.
Show contents:
NSLog(#"Documents directory: %#", [fileMgr contentsOfDirectoryAtPath:documentsDirectory error:&error]);
Get all files
//get an instance of the File Manager
NSFileManager *fileManager = [NSFileManager defaultManager];
//we'll list file in the temporary directory
NSString * strPath = NSTemporaryDirectory();
//we'll need NSURL for the File Manager
NSURL *tempDirURL = [NSURL fileURLWithPath:strPath];
//An array of NSURL object representing the path to the file
//using the flag NSDirectoryEnumerationSkipsHiddenFiles to skip hidden files
NSArray *directoryList = [fileManager contentsOfDirectoryAtURL:tempDirURL
includingPropertiesForKeys:nil
options:NSDirectoryEnumerationSkipsHiddenFiles error:nil];
Reference:http://www.ios-developer.net/iphone-ipad-programmer/development/file-saving-and-loading/using-the-document-directory-to-store-files
http://nshipster.com/nsfilemanager/
An iPhone's documents directory is used for saving data. We can save some personal data like as file, image, video etc. The document's directory's data will remain in the iPhone's memory until the application is forcibly terminated.
Let's see an example of how to store some images & retrieve those images later in an iPhone.
// For saving the images in the Document's Directory
-(void)saveImagesInIPhone:(NSData*)imageData withName:(NSString*)imageName
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//Get the docs directory
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
NSString *folderPath = [documentsDirectoryPath stringByAppendingPathComponent:#"IconImages"]; // subDirectory
if (![[NSFileManager defaultManager] fileExistsAtPath:folderPath])
[[NSFileManager defaultManager] createDirectoryAtPath:folderPath withIntermediateDirectories:NOattributes:nil error:nil];
//Add the FileName to FilePath
NSString *filePath = [folderPath stringByAppendingPathComponent:[iconName stringByAppendingFormat:#"%#",#".png"]];
//Write the file to documents directory
[imageData writeToFile:filePath atomically:YES];
}
Result:- /var/mobile/Applications/20F869FD-5C61-4900-8CFE-830907731EC9/Documents/Designer0.png
///To retrieve the images from the document Directory
-(UIImage*)retrieveImageFromPhone:(NSString*)fileNamewhichtoretrieve
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//Get the docs directory
NSString *documentsPath = [paths objectAtIndex:0];
NSString *folderPath = [documentsPath stringByAppendingPathComponent:#"IconImages"]; // subDirectory
NSString *filePath = [folderPath stringByAppendingPathComponent:
[fileNamewhichtoretrieve stringByAppendingFormat:
#"%#",#".png"]];
if([[NSFileManager defaultManager] fileExistsAtPath:filePath])
return [[UIImage alloc] initWithContentsOfFile:filePath];
else
return nil;
}
result :- /var/mobile/Applications/20F869FD-5C61-4900-8CFE-830907731EC9/Documents/Designer0.png
You can get Directory Path like this..
-(NSString *)getDBPath
{
//Searching a standard documents using NSSearchPathForDirectoriesInDomains
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDir = [paths objectAtIndex:0];
NSLog(#"I am in --> getDBPath==%#",paths);
return [documentDir stringByAppendingPathComponent:#"abcd_DB.sqlite"];
}
**If you are using iOS Devices-
You can get Your DB directly by using https://macroplant.com/iexplorer Application.
**If you are using Simulator.
Get the Path directory
In terminal : open directory Path(Past your Directory Path).
Copy your DB and brows it with Firefox or sqlite browser.
I'm having an issue with loading existing images from the App's Documents Folder after ad-hoc update.
I've searched the internet for answers and I've found that I must use relative paths to files in order for the path to remain the same when the App is updated.
Can someone please show me how to do it ?
Right now I use the following to save the files (images) when ImagePicker finishes:
NSString *imageFilename = [NSString stringWithFormat:#"%#-profilePhoto.jpg",[NSDate date]];
NSArray *paths = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
imagePath = [NSString stringWithFormat:#"%#/%#", paths, imageFilename];
Please help me out !
I've found the solution:
Instead of loading the images from the full path, I chose to make the system search for them after their name.
So instead of:
//Full path stored in a dictionary:
profilePhotoPath = [userDict objectForKey:#"profilepic"];
//Load the image from path:
profilePhoto = [[UIImage alloc] initWithContentsOfFile:profilePhotoPath];
I now use the following:
//Load image from documentsDirectory, filename
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
profilePhotoPath = [userDict objectForKey:#"profilepic"];
profilePhotoPath = [documentsDirectory stringByAppendingPathComponent:[profilePhotoPath lastPathComponent]];
profilePhoto = [[UIImage alloc] initWithContentsOfFile:profilePhotoPath];
By using "lastPathComponent" attribute I'm basically stripping out everything from the path except the filename and then I use NSSearch to give me my file.
This line makes the problem
NSArray *paths = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
Here the issue is the variable paths is of type NSArray not NSString
Change it to,
NSString *paths = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
or
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *paths = [path objectAtIndex:0];
I need to look for files with a specific type and put them in an array. I've found code like this:
NSArray* pdfs = [[NSBundle mainBundle]
pathsForResourcesOfType:#"pdf" inDirectory:nil];
But this code accesses my application bundle, not the Documents directory.
I also found this code for getting the Documents directory:
NSString* doc = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);;
However, I just don't get how to get the path for a pdf file inside the Documents folder. I already tried to change the values of the parameters for inDirectory: in pdfs to be #"~/Documents" and still it can't change the directory path.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
documentsDirectory = [documentsDirectory stringByAppendingPathComponent:#"abcd.pdf"];
BOOL success = [[NSFileManager defaultManager] fileExistsAtPath:documentsDirectory];
if (success == YES){
//Do your stuff here if file found at documents directory
}
else{
//file not found
}
To get the array of files at document directory :
NSError **error1;
NSArray *paths2 = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
NSString *documentsDirectory2 = [paths2 objectAtIndex:0];
NSArray *array = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectory2 error:error1];
[wordlist writeToFile:[[NSBundle mainBundle]
pathForResource:#"wordlist" ofType:#"txt"] atomically: YES];
wordlist is a NSMutableArray, and the rest you know what.
The problem is that nothing is saved in wordlist.txt when I run the codes in Xcode. In front of this code nslog shows that there are 4 objects in wordlist. How come?
Edit:
Right!
These codes work!:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *yourArrayFileName = [documentsDirectory stringByAppendingPathComponent:#"wordlist.txt"];
[wordlist writeToFile:yourArrayFileName atomically:YES];
NSLog (#"%#", yourArrayFileName);
Edit 29 august 2011.
NSString *documentsDirectory = #"/Users/YOURNAME/Desktop/";
NSString *appFile = [documentsDirectory stringByAppendingPathComponent:#"norsk.txt"];
NSString *content = #"æ ø å";
BOOL ok = [content writeToFile:appFile atomically:YES encoding:NSUnicodeStringEncoding error:nil];
if (!ok) {
NSLog(#"Error writing file !");
}
also works!
You can't write in you app's bundle.
You need to write in the user's directory. You can know more about it in this question.
There's three directory you can write in
NSDocumentDirectory : the document directory. The user will be able to see these file. This should be for user files only. Backed up by iTunes.
NSCachesDirectory : the cache directory is where you place things you app may need in the future, but that you can reconstruct. Not backed up by iTunes.
NSApplicationSupportDirectory : the application support is where you place your essential files for your application. Backed up by iTunes.
I've added a very simple .csv file to my app's NSDocumentDirectory using:
-(IBAction)exportModule:(id)sender{
NSString *fileName = #"exportedfile.csv";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *exportString = #"I've,been,exported";
NSData *testData=[exportString dataUsingEncoding:NSUTF8StringEncoding];
NSString *docDir = documentsDirectory;
NSString *completePath = [docDir stringByAppendingPathComponent:fileName];
[testData writeToFile:completePath atomically:YES];
if ([[NSFileManager defaultManager] fileExistsAtPath:completePath]) {
NSLog(#"Theres a file here!");
}
}
The app gets into the if statement printing "Theres a file here!", however I would like open the file and see if there were any problems in formatting the .csv.
If I were running on a physical device, I'd be able to open it up in iTunes and take a look there, but is there a way to examine the .csv while only using the simulator?
I have this at the beginning of all of my programs for using the simulator
NSLog(#"Documents: %#", [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]);