creating a plist file - iphone

I want to write an Array to a plist wich works fine when i manually create the plist in the document folder.
but When I check if the plist exist and if not to create it from the plist in main bundle nothing happen.....
i did it as in the Property List Programming Guide it is written.
NSString *plistRootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistPath = [plistRootPath stringByAppendingPathComponent:#"list.plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]) {
plistPath = [[NSBundle mainBundle] pathForResource:#"list" ofType:#"plist"];
}
what did I missed?
edit:
I tryed the function in an seperate App and it worked.
So I tryed It again:
NString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistPath = [rootPath stringByAppendingPathComponent:#"list.plist"];
self.ListArray = [NSMutableArray arrayWithContentsOfFile:plistPath];
NSLog(#"preSave: %#", [ListArray count]);
NSLog(#"%#", plistPath);
and the Log says:
2011-02-16 16:54:56.832 ListApp[3496:207] .../Library/Application Support/iPhone Simulator/4.0.2/Applications/267F55E4-A46A-42E0-9E1C-EAF26846F75F/Documents/list.plist
but there is no file in the Dir.!

NSString *DocPath=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
filePath=[DocPath stringByAppendingPathComponent:#"AlarmClock.plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath:filePath])
{
NSString *path=[[NSBundle mainBundle] pathForResource:#"AlarmClock" ofType:#"plist"];
NSLog(#"file path: %#",filePath);
NSDictionary *info=[NSDictionary dictionaryWithContentsOfFile:path];
[info writeToFile:filePath atomically:YES];
}
//***Try this...

I tryed the code on an other mac and there it works It's the same project.
can anyone explain me why the plist is created on one mac but not on the other?
on the IPhone also no plist is written?
I guess in both cases this is cause the array I write to the plist is empty:
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistPath = [rootPath stringByAppendingPathComponent:#"list.plist"];
NSMutableArray *currentArray = [[NSMutableArray alloc] initWithContentsOfFile:plistPath];
NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[selectet valueForKey:NAME], #"name",
nil];
NSLog(#" DIC. : %#", dictionary);
[currentArray addObject:[dictionary copy]];
NSLog(#" %#", currentArray);
[currentArray writeToFile:plistPath atomically:YES];
[currentArray release];
the dictionary has the entry but currentArray is empty....
And still it works on one mac. but not on the other and on the IPhone.
Edit:
For some reason it worked again.
To be sure I deleted the plist from the document folder and cleared all targets.
And now the Problem as before I can only write the plist when i write the dictionary to it but then i can only save the last one.
And reading the plist won't work either.
Can anyone Tell me why this happens and how I can solve it?
Edit 2:
I found the Problem: since X-Code won't create the plist when I write the array with the dictionary to the plist.When I wrote the dictionary to the plist so X-Code creates the plist but with a dictionary Root so I cant write the array to it and I also can't read it in an Array.....
I created a plist in the Resources folder with a Array Root and copy it when it not exist to document folder and now it works.....
isn't it amazing how such easy things can give you such an headache

Related

iPhone - Xcode cannot find plist, or plist is not read correctly

I am having an issue reading from a custom plist. I have found the Apple documentation, and many posts on here and elsewhere, but I cannot understand what I am doing wrong.
My plist is a dictionary with two strings (urls).
Here is my code that is just like Apple's and other sites:
- (void)accessPlistForURLDictionary
{
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0];
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"server_urls.plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath])
{
// if not in documents, get property list from main bundle
plistPath = [[NSBundle mainBundle] pathForResource:#"server_urls" ofType:#"plist"];
NSLog(#"bundle");
}
NSData *xml = [[NSFileManager defaultManager] contentsAtPath:plistPath];
NSString *error = nil;
NSPropertyListFormat format;
// convert static property liost into dictionary object
NSDictionary *plistDictionary = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:xml mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&error];
if (!plistDictionary)
{
NSLog(#"Error reading plist: %#, format: %d", error, format);
}
serverURL = [[plistDictionary objectForKey:#"Root"] objectForKey:#"get_firstview"];
NSLog(#"serverURL in accessPlist is: %#", serverURL);
}
Here is the log.... I don't get why serverURL (a string variable that is synthesized) is 'null'
2013-01-07 12:47:06.742 ME[2305:c07] bundle
2013-01-07 12:47:06.744 ME[2305:c07] serverURL in accessPlist is: (null)
2013-01-07 12:47:06.744 ME[2305:c07] serverURL is: (null)
The last check is done right before I use serverURL in viewDidLoad
I have the plist added in Build Settings (I think). It must be an issue with my code, but I can't find what.
There is easier way to load plist into NSDictionary
NSMutableDictionary *plistDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile: plistPath];
Try that.

Storing NSArray/NSMuatbleArray in File

I'm beginning to store an NSArray in file, but I keep getting nil as a response...
The Apple docs say that nil means your file doesn't exist, but I'm pretty sure mine does (I'm probably not building my path correctly)...
Here is the code that I use to store my NSArray in a file...
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"scorecards" ofType:#"dgs"];
NSArray *myArray = [[NSArray alloc] initWithObjects:#"J", #"ANA", #"MY", #"GDON", nil];
[myArray writeToFile:filePath atomically:YES];
NSArray *mynewArray = [NSArray arrayWithContentsOfFile:filePath];
NSLog(#"%#", [mynewArray objectAtIndex:2]);
I also took a screenshot of Xcode to show you guys that my file does exist...
The file is clearly saved in the group ScorecardsSaved and the file is called scorecards with the extension dgs (something I made up for my specific application - Dot Golf Scorecard - dgs)
Indeed, your file path uses the pathForResource method, thus it will point to a location in your application bundle, which is not writable.
Instead, you have to write to the application document directory on the device / simulator.
NSURL *documentsDirectory =
[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask] lastObject];
NSURL *fileURL = [documentsDirectory
URLByAppendingPathComponent:#"storecards.dgs"];
So if your bundle version of the document contains some seed data, copy it to the app documents directory first.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:FILE_NAME];
[myArray writeToFile:filePath atomically:YES];

write a dictionary to plist on iphone

I want to add a new dictionary to the existing plist file, how can I do that, I can read from the file, but with the same approach, writing doesn't work. My plist structure looks like this:
Root Array
|__item0 Dictionary
|__item1 Dictionary
|__item2 Dictionary
The code of writing to the file looks like this:
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [paths objectAtIndex:0];
NSString *plistPath = [documentDirectory stringByAppendingPathComponent:#"list.plist"];
if (![fileManager fileExistsAtPath:plistPath]) {
plistPath = [[NSBundle mainBundle] pathForResource:#"list" ofType:#"plist"];
}
NSMutableArray *dataRoot = [NSMutableArray arrayWithContentsOfFile:plistPath];
NSMutableDictionary *item = [[NSMutableDictionary alloc] init];
[item setObject:#"value1" forKey:#"1"];
[item setObject:#"value2" forKey:#"2"];
[item setObject:#"value3" forKey:#"3"];
[dataRoot addObject:item];
[dataRoot writeToFile:plistPath atomically:YES];
[item release];
Can anyone help me with this, thanks!
I have updated my code, but it still doesn't work...And the problem is list.plist file doesn't get copied to ~/Documents directory.
You are trying to write the main bundle which is no-no on iOS. Please read the A Few Important Application Directories.
But your coding boils down to the following:
Check if plist is not in Application_Home/Documents/
Copied original plist from main bundle is the answer to step 1 is false.
Open the plist in the Documents directory
Update NSMutableArray
Write to file the plist
I think code is not wrong.
Have you check plistPath, dataRoot, and item?
They have correct value?
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingPathComponent:#"list.plist"];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
bingoArray = [[NSMutableArray alloc] initWithContentsOfFile:filePath];
}
[bingoArray writeToFile:filePath atomically:YES];
You can only save primitive types by default.
try out this link.
http://deadpanic.com/howtosave
He explains how to save any object to disk by using NSCoding protocol.
If you are working only with primitives then I apologize for wasting your time. But this is the path I took to write my custom stuff to disk. And I thought it was just an array issue.
Edit:
I just noticed... It looks like you are trying to write to an array in the Main Bundle. These files are read only.
You need to save a copy of the file in the Documents directory.
try this out to find the documents directory
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
// Change your plistPath to be this
plistPath = [documentsDirectory stringByAppendingPathComponent:#"list.plist"];
[dataRoot writeToFile:plistPath atomically:YES];
put your plist in this folder and you can write to it.

How to write to plist successfully?

I am having trouble writing my file into the plist after going through many tutorials, other people's problems and attempting it for myself. I can read the plist with no problems but I cant update it. Below are my codes on how I am writing my data into the plist. Correct me if I made any mistake.
NSString *path = [[NSBundle mainBundle] pathForResource:#"EventAddress" ofType:#"plist"];
NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
NSArray* allmyData = [myDictionary allValues];
// creates and array to store only the event details
NSMutableArray *data = [[NSMutableArray alloc] initWithArray:allmyData];
[data addObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:tfAddress.text, #"Address", tvEvents.text, #"Events", nil]];
[myDictionary setValue:data forKey:#"Whampo"];
BOOL flag = [myDictionary writeToFile:path atomically:YES];
if (flag){
NSLog(#"write to plist success");
}
NSLog(#"%#", myDictionary);
[myDictionary release];
The path is correct, the file exists, my values in the textView and textField are in the array, but when it comes to the writeToFile, it does not reflect on the file located at the document directory.
EDIT 01:
I found this online, very similar to Nekto's suggestion. But I am thinking on how to implement my code with his. I think its pretty simple, but I cant seem to figure out how to.
NSArray *paths= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [paths objectAtIndex:0];
NSString *plistDirectory = [NSString stringWithFormat:#"%#/Enterprise",documentDirectory];
NSString *mPath = [plistDirectory stringByAppendingPathComponent:#"Downloads.plist"];
[mDownloadsArray writeToFile:mPath atomically:YES];
iphonesdk.blogspot taken from that site.
EDIT 02:
I used Nekto's suggestion and it worked well. But I am curious why it is returning DocumentsEventAddress.plist rather than EventAddress.plist. My assumption is because of the
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *plistPath = [rootPath stringByAppendingString:#"EventAddress.plist"];
Where rootPath is returning Document is that right?
I'm writing to file in such way:
NSString *errorDesc = nil;
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *plistPath = [rootPath stringByAppendingString:TEMPLATES_PATH];
NSDictionary *dict = [NSDictionary dictionaryWithObject:templates forKey:#"templates"];
NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:dict format:NSPropertyListXMLFormat_v1_0 errorDescription:&errorDesc];
if (plistData)
{
[plistData writeToFile:plistPath atomically:YES];
}else
{
NSLog(#"[Error] Application Did Enter Background {saving file error}: %#", errorDesc);
[errorDesc release];
}
Be sure to save file in app documents directory.
I don't believe you can write to a resource. Only files in the documents directory can be written to.
You can't write to files that are located in you Bundle.
The app bundle is read only.

writing NSDictionary to plist in my app bundle

I'm trying to write an NSDictionary to a plist but when I open the plist no data has been written to it.
From the log my path looks correct and my code is pretty standard.
Any ideas?
NSArray *keys = [NSArray arrayWithObjects:#"key1", #"key2", #"key3", nil];
NSArray *objects = [NSArray arrayWithObjects:#"value1", #"value2", #"value3", nil];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
for (id key in dictionary) {
NSLog(#"key: %#, value: %#", key, [dictionary objectForKey:key]);
}
NSString *path = [[NSBundle mainBundle] pathForResource:#"FormData" ofType:#"plist"];
NSLog(#"path:%#", path);
[dictionary writeToFile:path atomically:YES];
Johan is right -- you're not allowed to modify your app's bundle. You have two good options for where to save your dictionary: the documents directory, which is backed up by iTunes when a user syncs their device; or the caches directory, which is not backed up. If you don't need to have the data backed up, put it in caches so you don't slow down syncing. You can get the directory paths like so:
NSString *documentsDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *cachesDirectoryPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0];
It doesn't get saved because you can't write into your app's bundle. Save your file elsewhere, in the documents folder for example.