Write an array on.plist - objective-c

I have a problem. I have this file dictionary .plist:
<plist version="1.0">
<dict>
<key>2</key>
<array>
<string>a</string>
<string>b</string>
<string>c</string>
</array>
</dict>
</plist>
So now I read this file in this way:
NSString* plistPath = [[NSBundle mainBundle] pathForResource:#"dictionary" ofType:#"plist"];
NSMutableDictionary *contentArray = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
NSMutableArray *dic = [contentArray objectForKey:#"2"];
NSLog(#"Numero di elementi del dictionary corrispondente a 2: %i", [dic count]);
for (int i = 0; i < [dic count]; ++i) {
NSString *temp = [dic objectAtIndex:i];
NSLog(#"Stringa = %#\n", temp);
}
Now I want to modify the array:
[dic replaceObjectAtIndex:0 withObject:#"ok"];
and I want to write it on the dictionary.plist and I try this:
[contentArray writeToFile:plistPath atomically:YES];
[contentArray release];
But this code doesn't work, and I receive an error, how can I do this?
Thanks

Since you didn't provide the error, I assume the problem might be that
NSMutableDictionary * contentArray = [NSMutableDictionary dictionaryWithContentsOfFile: plistPath];
only creates a mutable container (you can change the content of contentArray, but not the objects (leaves) inside of it.
If you want mutable leaves, use NSPropertyListSerialization instead:
NSMutableDictionary * contentArray = [NSPropertyListSerialization propertyListFromData: [NSData dataWithContentsOfFile: plistPath] mutabilityOption: NSPropertyListMutableContainersAndLeaves format: nil errorDescription: nil];

Related

How can I extract a NSDictionary from an NSDictionary on a lower level

I have an NSDictionary that contains an NSDictionary which also contains NSDictionaries. Now I have code to extract what I need when I only have the website. This is my code.
NSInteger selectedRow = [self.myTableView selectedRow];
NSString *currentName = [self.theFullArray objectAtIndex:selectedRow];
NSMutableArray *theOriginalArray = [self.theDictionary.allKeys mutableCopy];
if ([self.theDictionary.allKeys containsObject:#"#"]) {
[theOriginalArray removeObject:#"#"];
}
NSMutableArray *sortedKeys = [[theOriginalArray sortedArrayUsingDescriptors:#[[NSSortDescriptor sortDescriptorWithKey:#"self" ascending:YES]]] mutableCopy];
if ([self.theDictionary.allKeys containsObject:#"#"]) {
[sortedKeys addObject:#"#"];
}
NSArray *theFullDictObjects = sortedKeys;
NSUInteger theFullDictCount = [theFullDictObjects count];
NSDictionary *currentInfo = nil;
int firstI = 0;
while (firstI < theFullDictCount) {
NSString *currentFullDictObject = [theFullDictObjects objectAtIndex:firstI];
NSDictionary *theSubDict = [self.theDictionary objectForKey:currentFullDictObject];
NSArray *theSubDictObjects = [theSubDict allKeys];
NSUInteger theSubDictCount = [theSubDictObjects count];
int secondI = 0;
while (secondI < theSubDictCount) {
NSString *currentDictObject = [theSubDictObjects objectAtIndex:secondI];
if ([currentName isEqualToString:currentDictObject]) {
NSDictionary *theDict = [theSubDict objectForKey:currentDictObject];
currentInfo = theDict;
break;
}
secondI++;
}
if (currentInfo) {
break;
}
firstI++;
}
NSLog(#"currentInfo: %#", currentInfo);
Now this works but it's kinda slow when you have really big lists of NSDictionaries. Is there another code to do this more effectively or not.
So let's says I have the value "www.adobe.com" then how can I get
<dict>
<key>Name</key>
<string>Adobe</string>
<key>Website</key>
<string>www.adobe.com</string>
<key>Sub Category</key>
<string>Technology</string>
<key>Category</key>
<string>Account</string>
<key>PRLCountry</key>
<string>Belgium</string>
</dict>
If you look at the image, you can see how the dictionary is build.
Thanks in advance.

Storing data from a plist file into an array

I have spent all of yesterday trying to figure this out with no luck at all. Here is the code im working with.
NSString *path = [[NSBundle mainBundle] pathForResource:#"file" ofType:#"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
NSArray *array = [NSArray arrayWithArray:[dict objectForKey:#"root"]];
for(int num = 0; num < 5; num++)
{
NSLog(#"my array:%#", array);
}
NSLog(#"items in my array: %lu", (unsigned long) [array count]);
Here are the views for the plist file im working with.
<plist version="1.0">
<dict>
<key>New item</key>
<string>hello</string>
<key>New item - 2</key>
<string>world</string>
<key>New item - 3</key>
<string>again</string>
<key>New item - 4</key>
<string>and</string>
<key>New item - 5</key>
<string>again</string>
</dict>
</plist>
This code does not return null like when i tried using an NSArray over the NSDictionary, but when i run it console does not print out any data retrieved from the plist. It just prints out:
my array:{}
my array:{}
my array:{}
my array:{}
my array:{}
items in my array: 0
If i try to print out dict by changing the NSLog to NSLog(#"my array:%#", array); i get this.
my array:(NULL)
my array:(NULL)
my array:(NULL)
my array:(NULL)
my array:(NULL)
items in my array: 0
Everything you could print for such plist is
NSLog(dict[#"new item"]);
Also you probably should use
for(int num = 0; num < array.count; num++)
{
NSLog(#"my array:%#", array[i]);
}
instead of
for(int num = 0; num < 5; num++)
{
NSLog(#"my array:%#", array);
}
Don't know what keys are in dictionary? No need to concern about keys in this case. Try this
NSString *path = [[NSBundle mainBundle] pathForResource:#"file" ofType:#"plist"];
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
if(dict.count != 0)
{
NSArray *array = [dict allKeys];
for(int num = 0; num < array.count; num++)
{
NSLog(#"my array item:%#", [dict objectForKey:array[num]]);
}
}
else
{
NSLog(#"Your dictionary is empty.");
}
Are you trying to put all the values form the dict into the array ?
If so add:
NSArray *array = [NSArray arrayWithArray:[dict allValues]];
//Check for file;
NSString *path = [[NSBundle mainBundle] pathForResource:#"file" ofType:#"plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath:path])
NSLog(#"NO FILE AT PATH: %#", path);
I found the issue. I had to create a build phase and add the plist files to it. That way when i use the pathToResource ofFile it has a file to find when i use the rest of the code.

Get an integer from a plist for Objective-C iPhone dev

I have the following DataAll.plist:
<array>
<dict>
<key>ID</key>
<integer>1</integer>
<key>Name</key>
<string>Inigo Montoya</string>
</dict>
....
</array>
I want to get the ID value from it. My code gets the Name correctly, but the ID is a weird value. Here's what I'm doing:
NSBundle *bundle = [NSBundle mainBundle];
NSString *plistPath = [bundle pathForResource:#"DataAll" ofType:#"plist"];
NSArray *array = [[NSArray alloc] initWithContentsOfFile:plistPath];
self.allData = array;
[array release];
NSDictionary *first = [[NSDictionary alloc]
initWithDictionary:[self.allData objectAtIndex:0]];
Data *firstData = [[Data alloc] init];
[firstData setData:first];
labelName.text = [firstData EXName];
labelID.text = [NSString stringWithFormat:#"%d",[[firstData EXID]];
[firstData release];
Here's my Data.h
#interface Data : NSObject {
NSNumber *EXID;
NSString *EXName;
}
#property (readwrite, retain) NSNumber *EXID;
#property (nonatomic, retain) NSString *EXName;
And Data.m
#implementation Data
#synthesize EXID;
#synthesize EXName;
- (void) setData: (NSDictionary *) dictionary {
self.EXName = [dictionary objectForKey:#"Name"];
NSNumber *ID = [dictionary objectForKey:#"ID"];
self.EXID = ID;
}
Many thanks in advance! This is my first post, so I apologize if formatting isn't correct.
The problem is in
[NSString stringWithFormat:#"%d",[[firstData EXID]];
EXID is an NSNumber* object and not an int so %d isn't what you want. You need to either replace %d with %# or unwrap the integer from the NSNumber by calling [EXID integerValue] or [EXID intValue]. Which return NSInteger and int respectively.
Just because your data is in the plist as an integer doesn't mean it is retrieved as one. At least not when you retrieve with [dict objectForKey:]. Furthermore, NSNumber and integer are not the same data type.
My guess is the latter is throwing you off. That is to say the implicit conversion to NSNumber. Add the following before you call setData and update your OP with the output.
NSLog(#"plist entry: %#", first);

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.!

Integers not properly returned from a property list (plist) array in Objective-C

In summary, I am having a problem where I read what I expect to be an NSNumber from an NSArray contained in a property list and instead of getting a number such as '1', I get what looks to be a memory address (i.e. '61879840'). The numbers are clearly correct in the property list. Anyone know why this may be happening and what I can do to fix it?
Below is my process for creating the property list and reading it back.
Creating the property list
I have created a simple Objective-C property list with arrays of integers within one root array:
<array>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<array>
<integer>1</integer>
<integer>2</integer>
<integer>5</integer>
</array>
... more arrays with integers ...
</array>
The arrays are NSArray objects and the integers are NSNumber objects. The property list has been created and serialized using the following code:
// factorArray is an NSArray that contains NSArrays of NSNumbers as described above
// serialize and compress factorArray as a property list, Factors-bin.plist
NSString *error;
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES)
objectAtIndex:0];
NSString *plistPath = [rootPath stringByAppendingPathComponent:#"Factors-bin.plist"];
NSData *plistData = [NSPropertyListSerialization
dataFromPropertyList:factorArray
format:NSPropertyListBinaryFormat_v1_0
errorDescription:&error];
Inspecting the created plist, all values and types are correct, leading me to believe that I've properly created the list.
Reading the property list
The property list is read in as Data and then converted to an NSArray:
NSString *path = [[NSBundle mainBundle] pathForResource:#"Factors" ofType:#"plist"];
NSData *plistData = [[NSData alloc] initWithContentsOfFile:path];
NSPropertyListFormat format;
NSString *error = nil;
NSArray *factorData = (NSArray *)[NSPropertyListSerialization
propertyListFromData:plistData
mutabilityOption:NSPropertyListImmutable
format:&format
errorDescription:&error];
Cycling through factorData to see what it contains is where I see the erroneous integers:
for (int i = 0; i < 10; i++) {
NSArray *factorList = (NSArray *)[factorData objectAtIndex:i];
NSLog(#"Factors of %d\n", i + 1);
for (int j = 0; j < [factorList count]; j++) {
NSLog(#" %d\n", (NSNumber *)[factorList objectAtIndex:j]);
}
}
I see all the correct number of values, but the values themselves are incorrect, i.e.:
Factors of 3
61879840 (should be 1)
61961200 (should be 3)
Factors of 4
61879840 (should be 1)
61943472 (should be 2)
61943632 (should be 4)
Factors of 5
61879840 (should be 1)
61943616 (should be 5)
Try logging the intValue of the NSNumber instead:
NSLog(#" %d\n", [(NSNumber *)[factorList objectAtIndex:j] intValue]);