Can not read plist from mainbundle - iphone

I am having some strange problem.
I cant read plist file from application mainbundle
the file is in the "copy bundle resource"
but somehow it can not be read
here is the code
NSLog(#"%#",[[NSBundle mainBundle] pathForResource:#"8chk" ofType:#"plist"]);
it prints (null) all the time
here is the screenshot
can anyone tell me what is going on?

I am afraid to say that , you are not adding this 8chk.plist to your target.

Drag and drop plist file again in project, make sure you tick on checkbox while adding file to project which is saying "copy file in ProjectName"
then use this code to make it accessible and read values from plist
NSString *path = [[NSBundle mainBundle] pathForResource: #"YourPLIST" ofType: #"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile: path];
[id obj = [dict objectForKey: #"YourKey"];
OR
// Reads the value of the custom key you added to the Info.plist
NSString *value = [mainBundle objectForInfoDictionaryKey:#"key"];
//Log the value
NSLog(#"Value = %#", value);

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"Info.plist"];
This might work. make sure to copy the plist to target and put it in root directory.also u can try to put the plist files where the apps default plist is kept.
:)

Hi Shoeb Amin please check your plist file is add inside Target->Copy Bundle resource

Your path is wrong. copy bundle resource should read just 8chk.plist, not 8chk.plist ..in resources/8chk if the project navigator shows the correct tree.

Related

iphone SDK:Can write data to plist on Simulator but can't do same thing at Device?

Why I can write information to plist on simulator
But can't do this on real iphone/ipod device ????
Is there exist an absolute path to put a .plist file in xcode project ???
Thanks for all reply and answers ~
code : this how I write text to plist from textfield
NSString *plistPath = [[NSBundle mainBundle] pathForResource:#"Password" ofType:#"plist"];
NSMutableDictionary *propertyList = [[NSMutableDictionary alloc] initWithContentsOfFile:plistPath];
[propertyList setValue:serialNumber.text forKey:#"serial_number"];
You can only write to your application's sandbox directory. Below is a function that will return the path to the Documents folder for you app.
- (NSString *)applicationDocumentsDirectory
{
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}

reading image from document folder

if i place a image.png file in my resource, iphone will be able to read it. if i place a image.png file in iphone document folder it doesn't read?
i am sending the image over from my server, into the document folder. no problem with that.
i thought iphone will auto find the image file either in resource folder or document folder?
i did write any code for my app to locate the folder of my image, just called it by its file name, which is correct.
any ideas?
thks
// Get path to doc folder
NSArray *docpaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [docpaths objectAtIndex:0];
NSString *docpath = [documentsDirectory stringByAppendingPathComponent:#"Data.plist"];
self.data = [NSArray arrayWithContentsOfFile:docpath];
done loading the plist from doc folder.
now i go to plist, get the file name and display for cell.
NSDictionary *dataItem = [data objectAtIndex:indexPath.row];
cell.icon = [UIImage imageNamed:[dataItem objectForKey:#"Icon"]];
how can i specifiy the image is in my document folder?
You can create an UIImage from a file by using imageWithContentsOfFile. However you can not read the file just specifying the name if it is in document folder. You need to get the path of your file. Check this answer to get an idea of how to get the file path of document folder.
-- edit
If your plist contains the file names in document folder, then append the filenames from plist to document folder path to get the full path. Hope it helps.
NSArray *docpaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [docpaths objectAtIndex:0];
NSDictionary *dataItem = [data objectAtIndex:indexPath.row];
NSString *imagePath = [documentsDirectory stringByAppendingPathComponent:[dataItem objectForKey:#"Icon"]];
cell.icon = [UIImage imageWithContentsOfFile:imagePath];

Read/Write to a plist file that comes bundled with the app

I am building an add-on to my app where the user can search for an item in a list that is pre-populated with data from a .plist file. It is an NSDictionary. If the term, the user searched for, does not exist, the user can tap a + button and add it so it is there the next time.
First of I thought it would be as easy as using the NSUserDefaults, but a few problems arises.
To have the list included I must place it in the bundle, but if it is there I can not add new key/value pairs to it. This I can only do with files situated in the Documents folder.
So I guess I have to bundle the plist, then on first run I'll move it to the documents folder and access it there.
This opens up the problem when I need to update the app, I guess it will overwrite the values the user put in.
Is there a secure, easy-understandable, right way to achieve the functionality I describe?
Thanks for any help given:)
Edit: **** the actual approach, as suggested by TheSquad and TomH *****
+ (NSMutableDictionary*) genericProducts {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [documentPaths objectAtIndex:0];
NSString *documentPlistPath = [documentsDirectory stringByAppendingPathComponent:#"GenericProducts.plist"];
NSString *bundlePath = [[NSBundle mainBundle] bundlePath];
NSString *bundlePlistPath = [bundlePath stringByAppendingPathComponent:#"GenericProducts.plist"];
if([fileManager fileExistsAtPath:documentPlistPath]){
NSMutableDictionary *documentDict = [NSMutableDictionary dictionaryWithContentsOfFile:documentPlistPath];
return documentDict;
} else {
NSError *error;
BOOL success = [fileManager copyItemAtPath:bundlePlistPath toPath:documentPlistPath error:&error];
if (success) {
NSMutableDictionary *newlySavedDict = [NSMutableDictionary dictionaryWithContentsOfFile:documentPlistPath];
return newlySavedDict;
}
return nil;
}
}
And for adding a new product to the list:
+ (void) addItemToGenericProducts:(NSString*) newProduct {
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [documentPaths objectAtIndex:0];
NSString *documentPlistPath = [documentsDirectory stringByAppendingPathComponent:#"GenericProducts.plist"];
NSMutableDictionary *documentDict = [NSMutableDictionary dictionaryWithContentsOfFile:documentPlistPath];
[documentDict setObject:newProduct forKey:[MD5Checksum cheksum:newProduct]];
[documentDict writeToFile:documentPlistPath atomically:YES];
}
I had the same thoughts with my sqlite database...
I end up doing exactly that, copy the bundled file into documents in order to be able to modify it.
What I have done is checking at each startup if the file exist, if it does not, copy it.
If you do an update of your App, the documents folder will not be touch, this means the copied file from the previous version will still be present.
The only issue is that if you want your plist to be upgraded you will have to handle that in your application. If you have to do so I suggest you use the NSUserDefault to check if a previous version of the app existed before...
The contents of the documents directory is not altered when an application is updated.
The contents of the documents directory are deleted when the user deletes the app.
When the app is run the first time write a flag to NSUserDefaults. On subsequent runs of the app, check for existence of the flag. (alternatively, you can just check for existence of the plist in he documents directory)

problem in reading files in iphone application!

I am reading a file in iphone app. Its Works Fine.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSLog(#"%#",documentsDirectory);
NSString *fileName = [NSString stringWithFormat:#"%#/test.txt",documentsDirectory];
NSLog(#"%#",fileName);
NSString *content = [[NSString alloc] initWithContentsOfFile:fileName
usedEncoding:nil
error:nil];
NSLog (#"%#",content);
}
works good when i am using filename as test.txt
But when i add another file in the resource suppose test1.txt then NSLog(#"%#",documentsDirectory) and NSLog(#"%#",fileName) shows the right result. But
NSLog (#"%#",content); prints null in the log. So what is the reason?
I am printing detail error and it prints
NSFilePath = "/Users/sam-xxx/Library/Application Support/iPhone Simulator/3.2/Applications/51197946-6042-4A90-AA39-F07F8A649308/Documents/test1.txt";
NSUnderlyingError = Error Domain=NSPOSIXErrorDomain Code=2 "Operation could not be completed. No such file or directory";
It would be best here to check to see if an error is returned:
NSError *error;
NSString *content = [[NSString alloc] initWithContentsOfFile:fileName
usedEncoding:nil
error: &error];
if (error) NSLog(#"Error !: %#", [error localizedDescription]);
That will (hopefully) give you a clue as to whats going on.
(Edited to give example bundle resource usage as the file is in the bundle not the Documents directory).
Docs for NSBundle are here: NSBundle Documentation
You have 2 choices, the one you suggest:
NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:fileName];
Which will return the Bundle resource directory with the filename appended to that path.
Personally I prefer the pathForResource:ofType: method:
NSString *filename = [[NSBundle mainBundle] pathForResource: #"test1" ofType: #"txt"];
As this will not only tell you if the file exists (returns nil if it does not) but will also search the localisation directories if you have them.
Did you check if the file in the error message exists? When run in the simulator you can simply open Finder, press cmd+shift+g and paste the directory to the file.
Maybe you didn't add it to the target? Open the information window for the file in your resources and check which targets are checked.
When you run a app in Simulator, you could copy and paste the right file into the app's Documents directory use Finder, but on iPhone or iTouch how could you paste a file into the Documents directory.
We got only 2 method to put something into Documents directory when app is running on iPhone or iTouch.
Create one.
Copy one from the bundle.
in your code, you read a file in the Documents directory, you could be paste a file in the directory manually use Finder. Try this.
NSString *path = [[NSBundle mainBundle] pathForResource:#"test.txt" ofType:nil];
NSString *content = [[NSString alloc] initWithContentsOfFile:path
usedEncoding:nil
error:nil];
NSLog (#"%#",content);

iPhone: Can access files in documents directory in Simulator, but not device

I'm writing an app that copies some contents of the bundle into the applications Document's directory, mainly images and media. I then access this media throughout the app from the Document's directory.
This works totally fine in the Simulator, but not on the device. The assets just come up as null. I've done NSLog's and the paths to the files look correct, and I've confirmed that the files exist in the directory by dumping a file listing in the console.
Any ideas? Thank you!
EDIT
Here's the code that copies to the Document's directory
NSString *pathToPublicationDirectory = [NSString stringWithFormat:#"install/%d",[[[manifest objectAtIndex:i] valueForKey:#"publicationID"] intValue]];
NSString *manifestPath = [[NSBundle mainBundle] pathForResource:#"content" ofType:#"xml" inDirectory:pathToPublicationDirectory];
[self parsePublicationAt:manifestPath];
// Get actual bundle path to publication folder
NSString *bundlePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:pathToPublicationDirectory];
// Then build the destination path
NSString *destinationPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%d", [[[manifest objectAtIndex:i] valueForKey:#"publicationID"] intValue]]];
NSError *error = nil;
// If it already exists in the documents directory, delete it
if ([fileManager fileExistsAtPath:destinationPath]) {
[fileManager removeItemAtPath:destinationPath error:&error];
}
// Copy publication folder to documents directory
[fileManager copyItemAtPath:bundlePath toPath:destinationPath error:&error];
I am figuring out the path to the docs directory with this method:
- (NSString *)applicationDocumentsDirectory {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
}
And here's an example of how I'm building a path to an image
path = [NSString stringWithFormat:#"%#/%d/%#", [self applicationDocumentsDirectory], [[thisItem valueForKey:#"publicationID"] intValue], [thisItem valueForKey:#"coverImage"]];
It turned out to be an issue where the bundle was not being updated on the device and apparently didn't have the same set of files that the Simulator had. This blog post helped a bit: http://majicjungle.com/blog/?p=123
Basically, I cleaned the build and delete the app and installed directly to the device first instead of the simulator. Interesting stuff.
I don't see where documentsDirectory is defined.
NSString *destinationPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%d", [[[manifest objectAtIndex:i] valueForKey:#"publicationID"] intValue]]];
Perhaps the following will do the trick
NSString *destinationPath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent:[NSString stringWithFormat:#"%d", [[[manifest objectAtIndex:i] valueForKey:#"publicationID"] intValue]]];
Your copy code looks fine, and you say you're getting no errors.
But I'm intrigued by "The assets just come up as null." Are you sure you're accessing the file name later with the exact same name?
Unlike the simulator, a real iPhone has a case sensitive file system.