How do .plist files work in iOS - iphone

I am new to iOS development, and I would like to know how .plist files work in iOS. Can any one help me by giving me an example of how to read an write data to and from a .plist?

Yup:
NSString *rootPath = [[NSBundle mainBundle] bundlePath];
NSString *pListPath = [rootPath stringByAppendingPathComponent:#"Settings.bundle/Root.plist"];
NSDictionary *pList = [NSDictionary dictionaryWithContentsOfFile:pListPath];
Writing to a file isn't too hard either:
NSDictionary *dict;
NSData *data = [NSPropertyListSerialization dataWithPropertyList:dict format:NSPropertyListXMLFormat_v1_0 options:0 error:&error];
[data writeToFile:self.saveToPath atomically:YES];

Related

iPhone - Populating an array with the content of compressed plist file

Let's say I have a plist file, and I want to compress it. I have a method that loads this compressed file, uncompress it, and put the result into a NSString.
How may I convert that NSString into an array as simple as it can be done with those lines when the plist is not compressed :
NSString* filePath = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"plist"];
NSArray* arrayOfDatas = [NSArray arrayWithContentsOfFile:filePath];
Read the file into an NSData then use:
+ (id)propertyListWithData:(NSData *)data options:(NSPropertyListReadOptions)opt format:(NSPropertyListFormat *)format error:(NSError **)error
where NSPropertyListFormat is NSPropertyListBinaryFormat_v1_0
Creating to NSData to write out is:
+ (NSData *)dataWithPropertyList:(id)plist format:(NSPropertyListFormat)format options:(NSPropertyListWriteOptions)opt error:(NSError **)error
Example (not tested):
NSString* filePath = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"plist"];
NSData *data = [NSData dataWithContentsOfFile:filePath];
NSError *error;
NSArray* plist = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:NULL error:&error];
NSData *propertyListSerializedData = [NSPropertyListSerialization dataWithPropertyList:plist format:NSPropertyListBinaryFormat_v1_0 options:0 error:&error];
[propertyListSerializedData writeToFile:filePath atomically:YES];

reading from plist issue

I have a plist which is an array, the file name is called startups.plist. I tried to read it into an array by the following code:
NSString *path = [[NSBundle mainBundle] pathForResource:#"startups" ofType:#"plist"];
NSMutableArray * wordList = [[NSMutableArray alloc] initWithContentsOfFile:path];
However, wordList is always 0 here. Printed the path when testing on device, and it gives me:
/var/mobile/Applications/CCBF94D9-389C-4D63-B023-F39653FDCEF4/My.app/startups.plist
Here's what the structure looks like of the plist:
the size of the array is 0.
What am I doing wrong here?
initWithContentsOfFile: will not open plist file. Here is a sample:
NSString *errorDesc = nil;
NSPropertyListFormat format;
NSString *path = [[NSBundle mainBundle] pathForResource:#"startups" ofType:#"plist"];
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:path];
NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization
propertyListFromData:plistXML
mutabilityOption:NSPropertyListMutableContainersAndLeaves
format:&format
errorDescription:&errorDesc];
NSLog(#"%#",[temp objectForKey:#"Root"]);
You have to use NSDictionary since your plist is a Dictionary which has a key Root which is an array.
NSString *path = [[NSBundle mainBundle] pathForResource:#"startups" ofType:#"plist"];
NSMutableDictionary * dict = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
NSMutableArray *wordList = (NSMutableArray *)[dict objectForKey:#"Root"];
I'm not sure about casting to NSMutableArray. Maybe you have to do
NSMutableArray *wordList = [NSMutableArray arrayWithArray:(NSArray*)[dict objectForKey:#"Root"]]

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.

Read RTFD data in IOS

I have RTFD data in NSData objects in IOS that I need to read. In MacOSX I just used to read them with NSAttributedString, but now I know that they are not supported in IOS.
attribString = [[NSAttributedString alloc] initWithRTFD:note documentAttributes:&dict];
Is there any way to read only the text of the RTFD data in IOS?
The rtfd in iOS is something like as a directory. If you only want to get the text part, you can try:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"photo" ofType:#"rtfd"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *content = [fileManager contentsOfDirectoryAtPath:filePath error:nil];
NSString *textFilePath = [filePath stringByAppendingPathComponent:#"TXT.rtf"];//you can get the path component from the content; usually it is TXT.rtf
NSError *error = nil;
NSString *pureText = [[NSString alloc] initWithContentsOfFile:textFilePath encoding:NSASCIIStringEncoding error:&error];
NSLog(#"pureText:\n%#",pureText);
Hope it can help.

How to save a value in a plist file in iPhone?

I am new to iPhone development. I am using the below code to add the value to the plist but when check the plist after executing the code I don't see any value saved in the plist. Where did I go wrong? The plist I have created is in the resource folder.
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"regvalue.plist"];
NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:finalPath];
[plistDict setValue:#"hello" forKey:#"choice"];
[plistDict writeToFile:finalPath atomically: YES];
For retrieving the value
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"regvalue.plist"];
NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:finalPath];
NSString *value;
value = [plistDict objectForKey:#"choice"];
NSLog(#"the value is %#",value);
It gives only null value.
The resources folder is not writeable. You should save it into the documents folder.
Maybe you can find the answer here:
How to write data in plist?
But if you only want save some message in you app, NSUserDefaults is the better way.