writing NSDictionary to plist in my app bundle - iphone

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.

Related

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

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.

How can we create our own plist file in a Xcode project?

I want to create "UrlPaths.plist" file in my Application and also a dictionary with 4 or 5 objects. Please help me create a plist file and dictionary. And also read data from that plist file.
I want the plist to add the file to resources folder and i want to add Dictionary at that time also.i dont want pragmatical creation of plist but i want reading the data is pragmatically.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"plist.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSMutableDictionary *data;
if ([fileManager fileExistsAtPath: path]) {
data = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
}
else {
// If the file doesn’t exist, create an empty dictionary
data = [[NSMutableDictionary alloc] init];
}
//To insert the data into the plist
data[#"value"] = #(5);
[data writeToFile: path atomically:YES];
[data release];
//To retrieve the data from the plist
NSMutableDictionary *savedStock = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
int value1;
value1 = [savedStock[#"value"] intValue];
NSLog(#"%i",value1);
[savedStock release];
If you are about to create Plist without programmatically then follow these steps :
1. Right Click on Files in Left Pane and Select 'New File...' option.
2. Choose Resources from OS X tab.
3. An option for Property List is available.
4. Select an give an appropriate name.
This gets added to your project.
We can get simple understanding about plist as below
Now you can read this data as below
NSString *path = [[NSBundle mainBundle] pathForResource:#"Priority" ofType:#"plist"];
NSDictionary *dictPri = [NSDictionary dictionaryWithContentsOfFile:path];//mm
NSMutableArray *arrMarkets=[[NSMutableArray alloc] initWithArray:[dictPri valueForKey:#"List"]];
NSMutableArray *arrForTable=[[NSMutableArray alloc] init];
NSMutableArray *arrForTable1=[[NSMutableArray alloc] init];
for (NSDictionary *dict in arrMarkets)
{
NSString *strS1=nil;
strS1= [NSString stringWithFormat:#"%#",[dict valueForKey:#"Description"] ];
[arrForTable addObject:strS1];
}
NSLog(#"%#----------------- ",[arrForTable description]);
for (NSDictionary *dict in arrMarkets)
{
NSString *strS2=nil;
strS2= [NSString stringWithFormat:#"%#",[dict valueForKey:#"Name"] ];
[arrForTable1 addObject:strS2];
}
NSLog(#"%#----------------- ",[arrForTable1 description]);
create new plist file -
NSArray *Arr = [NSArray arrayWithObjects:obj1,obj2,nil];
NSData *data = [NSPropertyListSerialization dataFromPropertyList:Arr format:NSPropertyListXMLFormat_v1_0 errorDescription:nil];
[data writeToFile:PlistDataFilePath atomically:YES];
Read data from this plist file -
NSData *data = [NSData dataWithContentsOfFile:PlistDataFilePath];
NSPropertyListFormat format;
NSArray *array = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:NSPropertyListImmutable format:&format errorDescription:nil];
you should read this great tut on plist files - http://www.edumobile.org/iphone/iphone-programming-tutorials/how-to-use-plist-in-iphone/

Not able to write to Plist

I have a very basic question about how to write to a plist. I added a "Here.plist" file to my resources folder. The following is my code:
NSString *path = [[NSBundle mainBundle]pathForResource:#"Here" ofType:#"plist"];
NSArray *array = [[NSArray alloc]initWithObjects:#"First", #"Second", #"Third", nil];
[array writeToFile:path atomically:YES];
"Here.plist" is still empty after executing the code. I even tried using a NSDictionary as follows:
NSDictionary *dict = [[NSDictionary alloc]initWithObjectsAndKeys:#"firstValue", #"First", #"secondValue", #"Second", #"thirdValue", #"Third", nil];
[dict writeToFile:path atomically:YES];
I went through many tutorials and forums but its just not working for me. What am i doing wrong? Losing my head over this.
You can't write into the bundle. Try writing into the documents directory. For example:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSArray *array = [[NSArray alloc]initWithObjects:#"First", #"Second", #"Third", nil];
[array writeToFile:[documentsDirectory stringByAppendingPathComponent:#"Here.plist" atomically:YES];
I suspect your problem is due to the fact that you can't write to the application bundle, only to your application's document store.
To obtain a path to the document store, use:
NSArray *searchPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docStorePath = [searchPaths objectAtIndex:0];
NSString *filePath = [docStorePath stringByAppendingPathComponent:#"XXXXX"];

creating a plist file

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