Read binary plist into NSDictionary - objective-c

Is there simple way to parse the binary plist file into the NSDictionary representation?
I am searching something like that:
NSString* strings = [NSString stringWithContentsOfURL: ... encoding: NSUnicodeStringEncoding error: ...];
NSMutableDictionary* pairs = (NSMutableDictionary*)[strings propertyListFromStringsFileFormat];
Using this code caused the exception while parsing the binary plist file.

Are you looking for [NSDictionary dictionaryWithContentsOfFile:]?

Considering a file called DataStorageFile.plist, you can use:
NSString *dataPath = [[NSBundle mainBundle] pathForResource:#"DataStorageFile" ofType:#"plist"];
self.data = [NSDictionary dictionaryWithContentsOfFile:dataPath];
If you want an array:
self.data = [NSArray arrayWithContentsOfFile:dataPath];

Related

Accessing a second NSDictionary in the plist?

I was wondering how I could access the second NSDictionary in my plist other then the root dictionary, what I would like is to have a string in the second dictionary to show up in the console right now I'm getting all of them. Here's my code, console and plist.
My Plist. (its name is Multi.plist)
My code.
NSString *pathForPlist = [[NSBundle mainBundle] pathForResource:#"Multi" ofType:#"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:pathForPlist];
NSLog(#"%#", [dict objectForKey:#"Abs"]);
And what my console is spitting out right now.
So after looking at that, I'll explain again what I would like, instead of having all of the contents of the Abs NSDictionary being in the console, I would like just to show the title string which lies within the Dictionary. Any help would be greatly appreciated.
Thanks
The Abs entry is a dictionary itself, so all you have to do is :
NSDictionary * abs = dict[#"Abs"];
NSLog(#"%#", abs[#"title"]);
NSDictionary *absDict = [dict objectForKey:#"Abs"]);
NSString *title = [absDict objectForKey:#"title"]);
NSLog(#"Title: %#", title);

How to save an array with float values into a text file that is readable by Mac?

I want to save float values stored in an array into a text file and read the file directly on Mac. This is how I create the array:
dataArray = [[NSMutableArray alloc] init];
NSNumber *numObj = [NSNumber numberWithFloat:3.14];
[dataArray insertObject:numObj atIndex:0];
NSNumber *numObj = [NSNumber numberWithFloat:2.3];
[dataArray insertObject:numObj atIndex:1];
...
This is how I save the array:
NSData *savedData = [NSKeyedArchiver archivedDataWithRootObject:dataArray];
NSString *filePath = #"/Users/smith/Desktop/dataArray.txt";
[savedData writeToFile:filePath options:NSDataWritingAtomic error:nil];
When I open the file, the contents are just garbled letters. Instead, I want to make it something like this:
3.14
2.3
1.4
...
the program you've written saves the object representation as an array of NSNumbers, while
the result you want/expect is a text file separated by newlines.
to save those float values into a text file of that format, you could to this:
...
NSMutableString * string = [NSMutableString new];
[string appendFormat:#"%f\n", 3.14];
[string appendFormat:#"%f\n", 2.3];
NSError * error = nil;
BOOL written = [string writeToURL:url atomically:YES encoding:someEncoding error:&error];
...
You can use componentsJoinedByString: to make an in-memory representation first, and then write that representation into a file, like this:
NSString *fileRep = [dataArray componentsJoinedByString:#"\n"];
NSString *filePath = #"/Users/smith/Desktop/dataArray.txt";
[fileRep writeToFile:filePath options:NSDataWritingAtomic error:nil];
This assumes that the number of items is relatively small, because the string representation is created entirely in memory.
Reading back is not as nice as writing out, though: you start by reading back a string, theb split it to components using [fileRep componentsSeparatedByString:#"\n"], and then go through components in a loop or with a block, adding [NSNumber numberWithDouble:[element doubleValue]] for each element of your split.
You probably want to create an XML plist from it to make it human-readable:
[dataArray writeToFile:filePath atomically:YES];
This creates a property list, which is human-readable XML (except if the file already exists AND it's a binary plist, in this case the new plist will also be binary).

Reading from plist to NSArray

I am trying to read and I also need to write to a plist.
So far I am trying to simply read the contents in.
Here is my appSettings.plist:
NSBundle* bundle = [NSBundle mainBundle];
NSString* plistPath = [bundle pathForResource:#"appSettings" ofType:#"plist"];
NSDictionary *tmp = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
I tried to do this:
NSArray *mruItems = [[NSArray alloc] initWithArray:[tmp objectForKey:#"lastSearches"]];
But it throws an error. A check I did on the [tmp objectForKey:#"lastSearches"] type revealed this is not an NSArray...
How can I read the contents into my NSArray?
Thanks!
(I would love to have some info on writing too)
If you look at the screenshot above you see that it's pretty clear that "lastSearches" is a Dictionary, not a list. You can try to switch the type there to a Array type instead and it should work for you.
Another solution would be to iterate over the keys in that dictionary:
NSDictionary *lastSearches = [tmp objectForKey:#"lastSearches"];
for (NSString *key in lastSearches.allKeys)
{
NSString *value = [lastSearches objectForKey:key];
}
Note that this would not be in order, and you probably would have to sort before iterating over it.
Indeed it's not an array but a dictionary (look at your image).

Editing a plist in NSDictionary

I'm importing a plist into an NSDictionary object and want to change the contents of the plist once in the dictionary to lowercase. I have tried several different ways with no luck. Maybe I am supposed to edit the strings that are inside the NSDictionary, but then I don't know how to do that.
What I have currently imports the plist correctly, but the lowercaseString line effectively does nothing.
NSString *contents = [[NSBundle mainBundle] pathForResource:#"Assets/test" ofType:#"plist"];
NSString *newContents = [contents lowercaseString];
NSDictionary *someDic = [NSDictionary dictionaryWithContentsOfFile:newContents];
for (NSString *someData in someDic) {
NSLog(#"%# relates to %#", someData, [someDic objectForKey:someData]);
}
I NSLog'd the "content" string and it gave me a path value, so obviously changing that to a lowercaseString wouldn't do anything. I'm feeling like I have to access the strings within the dictionary.
This line
NSString *newContents = [contents lowercaseString];
is change the path string returned from
NSString *contents = [[NSBundle mainBundle] pathForResource:#"Assets/test" ofType:#"plist"];
so you will end up with something like ../assets/test.plist
you will need to walk through the contents of someDic an create a new dictionary based on the old turning strings into lowercase, if you are only concerned about values directly in someDic you can do something like
for( NSString * theKey in someDic )
{
id theObj = [someDic objectForKey:theKey];
if( [theObj isKindOfClass:[NSString class]] )
theObj = [theObj lowercaseString];
[theNewDict setObject:theObj forKey:theKey];
}

access plist data

i have a plist which goes like this:
<dict>
<key>11231654</key>
<array>
<string>hello</string>
<string>goodbye</string>
</array>
<key>78978976</key>
<array>
<string>ok</string>
<string>cancel</string>
</array>
i've load the plist using this:
NSString *path = [[NSBundle mainBundle] pathForResource:
#"data" ofType:#"plist"];
// Build the array from the plist
NSMutableArray *array3 = [[NSMutableArray alloc] initWithContentsOfFile:path];
how can i access each element of my plist?
i want to search for a matching key in the plist and than search with its child. how can i do this? any suggestion?
thks in advance!
Arrays are indexed. If you wanted to access the first object in an NSArray, you’d do the following:
id someObject = [array objectAtIndex:0];
If you know the object type, you could do it like this:
NSString *myString = [array objectAtIndex:0];
EDIT: You need to use an NSDictionary for the data that you have—note that it starts with a <dict> tag, not an <array> tag (though there are arrays as values).
NSString *path = [[NSBundle mainBundle] pathForResource:
#"data" ofType:#"plist"];
// Build the array from the plist
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
NSArray *value = [dict valueForKey:#"11231654"];
Now you can do whatever you want with your array.
Here is a link to a discussion that provided a very good example of how to access your data and which type of storage schemes would be more beneficial under certain circumstances. #Jeff Kelley's solution is on target, I just thought this question would add an additional resource. Hope this helps!
This is how you need to create plist
Set root to array instead of dictionary , this will give you results in sequence.
With below lines of code you can fetch complete plist.
NSString *pathOfPlist = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"plist"];
arrPlistValue = [[NSArray alloc]initWithContentsOfFile:path];
NSLog(#"Plist Value : %#",arrPlistValue);
After that you can fetch any specific content with below code:
NSString *strName = [[arrTempValue objectAtIndex:0] objectForKey:#"name"];
NSString *strImage = [[arrTempValue objectAtIndex:0] objectForKey:#"image"];
int idValue = [[[arrTempValue objectAtIndex:0] objectForKey:#"id"] integerValue];
BOOL isSubCat = [[[arrTempValue objectAtIndex:0] objectForKey:#"isSubCategory"] boolValue];
With this code you can fetch integer , string , boolean from plist.!