iPhone - parsing a plist file into an array without success - iphone

I try to put a plist file content into an array using this functions :
NSString *path = [[NSBundle mainBundle] pathForResource:#"DataFile" ofType:#"plist"];
self.contentData = [NSArray arrayWithContentsOfFile:path];
But self.contentData keeps being null...
I don't understand why. I used the same code than the one shown in the Apple "PageControl" sample project (See here), using also a pList file with the same structure (list of Dictionary items with 2 strings inside).
path is filled with : /var/Mobile/Applications/somehexvalues/MyApp.app/DataFile.plist
How could I know what is going wrong ?
NSLog(#"%#", [NSDictionary dictionaryWithContentsOfFile:path]); gives :
"Item 0" = {
imageKey = "hearts.png";
nameKey = Hearts;
};
"Item 1" = {
imageKey = "leef.png";
nameKey = Leef;
};
"Item 2" = {
imageKey = "round.png";
nameKey = Round;
};

Your PLIST has an NSDitionary instead of an NSArray, that is why you get null. If you try to load an NSArray into a NSDcitionary, you will get null as well.

Related

How to create an array with particular item from a dictionary?

I have an application in which i am having the details of the members as a dictionary.i want to add an array with particular object from the dictionary.The response i am having is like this,
{
500 = {
name = baddd;
status = "<null>";
};
511 = {
name = abyj;
status = "Hi all...:-)";
};
512 = {
name = abyk;
status = fdffd;
};
}
I want to create an array with the results of name only.i have tried like this
for(int i=0;i<=self.currentChannel.memberCount;i++)
{
NSString *name=[NSString stringWithFormat:#"%#",[self.currentChannel.members objectForKey:#"name"]] ;
NSLog(#"%#",name);
[searchfriendarray addObject:name];
}
NSLog(#"%#",searchfriendarray);
but the value added is null. can anybody help me ?
Traverse objectEnumerator to get the values (inner dictionaries). Then just add the value of "name" to the resulting array. Example (assuming the dictionary is named d):
NSDictionary* d = ...
NSMutableArray* array = [NSMutableArray arrayWithCapacity:d.count];
for(NSDictionary* member in d.objectEnumerator) {
[array addObject:[member objectForKey:#"name"]];
}
Krumelur was faster than me ;) He is right by saing that you should traverse the dictionary values first. In your implementation you don't reference your counter variable i somewhere, so the NSString name is the same in each iteration.
This may help you..
// here you can get Array of Dictionary First
NSArray *arr = [[NSArray alloc] initWithContentsOfFile:#""]; // get array first from your response
NSDictionary *temp = [[NSDictionary alloc] initWithDictionary:self.currentChannel.members];
for(int i=0;i<=self.currentChannel.memberCount;i++)
{
NSDictionary *temp = [arr objectAtIndex:i];
NSString *name=[NSString stringWithFormat:#"%#",[temp objectForKey:#"name"]] ;
NSLog(#"%#",name);
[searchfriendarray addObject:name];
}
NSLog(#"%#",searchfriendarray);
Thanks.

How to get data from JSON data

I have JSON like this:
[{"ID" : "351", "Name" : "Cam123 ", "camIP" : "xxx.xxx.xxx.xxx",
"Username" : "admin", "Password" : "damin", "isSupportPin" : "1" },
{"ID" : "352", "Name" : "Cam122 ", "camIP" : "xxx.xxx.xxx.xxx",
"Username" : "admin", "Password" : "damin", "isSupportPin" : "0" }
]
I want to get isSupportPin with result: 1 or 0.
if (x == 1)
{
mybutton.enabled = TRUE;
}
else
{
mybutton.enabled = FALSE;
}
How I can do it?
Assuming you have an NSData object with this data in it:
// Your JSON is an array, so I'm assuming you already know
// this and know which element you need. For the purpose
// of this example, we'll assume you want the first element
NSData* jsonData = /* assume this is your data from somewhere */
NSError* error = nil;
NSArray* array = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
if( !array ) {
// there was an error with the structure of the JSON data...
}
if( [array count] > 0 ) {
// we got our data in Foundation classes now...
NSDictionary* elementData = array[0]; // pick the correct element
// Now, extract the 'isSupportPin' attribute
NSNumber* isSupportPin = elementData[#"isSupportPin"];
// Enable the button per this item
[mybutton setEnabled:[isSupportPin boolValue]];
} else {
// Valid JSON data, but no elements... do something useful
}
The above example code snippet assumes you know which element you want to read (I guess these are user lines or something) and that you know what the JSON attribute names are (e.g., if isSupportPin isn't actually defined in the JSON object returned in that array, it will simply return nil, which will always evaluate to NO when you send it -boolValue).
Finally, the above code is written for ARC and requires Xcode 4.5 or Clang 4.1 and a deployment target of iOS 5.0. If you're not using ARC, building with a legacy version of Xcode, or targeting something earlier than 5.0, you'll have to adjust the code.
Here what you have is an NSArray of NSDictionarys. So using SBJSON library you could do as following
SBJsonParser *parser = [SBJsonParser alloc] init];
NSArray *data = [parser objectFromString:youJson];
for (NSDictionary *d in data)
{
NSString *value = [d objectForKey:#"Name"];
}
The library can be found at http://stig.github.com/json-framework/
Follow the below link that my help you.
http://www.xprogress.com/post-44-how-to-parse-json-files-on-iphone-in-objective-c-into-nsarray-and-nsdictionary/
If you want to get data or Dictionary fron JSONData then use bellow code..
NSString *responseString = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
NSArray *resultsArray = [responseString JSONValue];
for(NSDictionary *item in resultsArray)
{
NSDictionary *project = [item objectForKey:#"result"];//use your key name insted of result
NSLog(#"%#",project);
}
and also download JSON Library and tutorial from below link...
http://mobileorchard.com/tutorial-json-over-http-on-the-iphone/

Adding values into my plist

I have this plist that I have created
I have written most of my controller class which gets this plist and loads it into the documents directory so its possible to read/write to is.
Currently I have the reading working fine, and I used to have the writing working also, however I have just recently changed one of the objects (cache value) to a Dictionary with values related to that. Now when I try to write to this plist my app is crashing.
This is the error I am getting.
2012-04-05 09:26:18.600 mycodeTest[874:f803] * Terminating app due to
uncaught exception 'NSInvalidArgumentException', reason: '*
-[NSDictionary initWithObjects:forKeys:]: count of objects (4) differs from count of keys (5)'
*** First throw call stack: (0x12cc022 0x1884cd6 0x1248417 0x12685e2 0x19844 0x17e86 0x17669 0x13b67 0xe53a49 0xe51e84 0xe52ea7 0xe51e3f
0xe51fc5 0xd96f5a 0x1d2aa39 0x1df7596 0x1d21120 0x1df7117 0x1d20fbf
0x12a094f 0x1203b43 0x1203424 0x1202d84 0x1202c9b 0x21aa7d8 0x21aa88a
0x450626 0x77ed 0x1e35 0x1) terminate called throwing an
exceptionCurrent language: auto; currently objective-c
with all of this in mind I will now show you my method, which is called from another class when it has the values ready to be saved.
//This method gets called from another class when it has new values that need to be saved
- (void) saveData:(NSString *)methodName protocolSignature:(NSString *)pSignature protocolVersion:(NSNumber *)pVersion requestNumber:(NSNumber *)rNumber dataVersionReturned:(NSNumber *)dvReturned cacheValue:(NSMutableDictionary *)cValue
{
// get paths from root direcory
NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
// get documents path
NSString *documentsPath = [paths objectAtIndex:0];
// get the path to our Data/plist file
NSString *plistPath = [documentsPath stringByAppendingPathComponent:#"EngineProperties.plist"];
// set the variables to the values in the text fields that will be passed into the plist dictionary
self.protocol = pSignature;
self.Version = pVersion;
self.request = rNumber;
self.dataVersion = dvReturned;
//if statment for the different types of cacheValues
if (methodName == #"GetMan")
{
//cache value only returns the one cachevalue depending on which method name was used
[self.cacheValue setValue:cValue forKey:#"Man"]; //do I need to have the other values of cacheValue dictionary in here? if so how do I do that.
c
}
else if (methodName == #"GetMod")
{
[self.cacheValue setValue:cValue forKey:#"Mod"];
}
else if (methodName == #"GetSubs")
{
[self.cacheValue setValue:cValue forKey:#"Subs"];
}
// This is where my app is falling over and giving the error message
// create dictionary with values in UITextFields
NSDictionary *plistDict = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects: protocol, pVersion, rNumber, dvReturned, cacheValue, nil] forKeys:[NSArray arrayWithObjects: #"Signature", #"Version", #"Request", #"Data Version", #"Cache Value", nil]];
NSString *error = nil;
// create NSData from dictionary
NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:plistDict format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];
// check is plistData exists
if(plistData)
{
// write plistData to our Data.plist file
[plistData writeToFile:plistPath atomically:YES];
NSString *myString = [[NSString alloc] initWithData:plistData encoding:NSUTF8StringEncoding];
NSLog(#"%#", myString);
}
else
{
NSLog(#"Error in saveData: %#", error);
// [error release];
}
}
I am abit lost when the error is saying that 4 keys differ from 5 when as far as i can tell i am applying 5 values to the dictionary any help would be appreciated.
Edit** another thing I noticed when debugging my issues was the fact it looks like I am not getting my cacheValue dictionary set up properly as its showing 0 key valuepairs??? is this right or wrong?
this is what happens when I log my plist in xcode as suggested below when I use [NSDictionary dictionaryWithObjectsAndKeys:..etc
Check setup is everything there?
Temp Dic output = {
Root = {
"Cache Value" = {
Manu = 0;
Mod = 0;
Sub = 0;
};
"Data Version returned" = 0;
"Signature" = null;
"Version" = 0;
"Request Number" = 0;
};
Run Man cache check results
Temp Dic output = {
"Version returned" = 5;
"Signature" = Happy;
"Version" = 1;
"Request Number" = 4;
as you can see Cache Value is completely missing after I have run the request.
I'm going to guess that cacheValue is nil when the crash occurs, resulting in only 4 objects in your values array, but 5 in keys.
Try using [NSDictionary dictionaryWithObjectsAndKeys:] instead.
In a situation like this, break up your code. Do each piece on a separate line, with temporary variables.
Put your keys and your values into temporary arrays.
Lot the values of everything, or set breakpoints in the debugger and examine all your values. Eli is almost certainly right that cacheValue is nil. The arrayWithObjects method stops on the first nil.
This code:
NSString *string1 = #"string 1";
NSString *string2 = #"string 2";
NSString *string3 = #"string 3";
NSString *string4 = nil;
NSString *string5 = #"string 5";
NSArray *anArray = [NSArray arrayWithObjects:
string1,
string2,
string3,
string4,
string5,
nil];
NSLog(#"anArray has %d elements", [anArray count]);
Will only show 3 elements in the array, even though the arrayWithObjects line appears to add 5 elements

Getting value from NSDictionary to NSMutableArray

I have this NSDictionary:
Categorys = {
Category = (
{
categoryDescription = {
text = " Description";
};
categoryIconPath = {
text = " 7.jpg";
};
categoryId = {
text = " 25";
};
categoryName = {
text = " My Photos";
};
categoryStatus = {
text = " ON";
};
publicPrivate = {
text = " Private";
};
userId = {
text = " 2";
};
},
..................
I want to get the categoryName (like here My Photos) into my NSArray.
How can I do this?
I am unable to get it
I have tried this code from http://troybrant.net/blog/2010/09/simple-xml-to-nsdictionary-converter/
NSString *category = [[[[xmlDictionary objectForKey:#"Categorys"] objectForKey:#"Category"] objectForKey:#"categoryName"] stringForKey:#"text"];
but it gives error
2012-03-27 15:30:35.320 File[1481:903] -[NSCFArray objectForKey:]: unrecognized selector sent to instance 0x1462c0
In Categories, the object referenced by the Category key is an array, you can tell by the fact that its contents are bracketed by parentheses ( ... ) not braces { ... }.
Looking at your code and breaking it down:
NSString *category = [[[[xmlDictionary objectForKey:#"Categorys"] // This is the outermost dictionary
objectForKey:#"Category"] // This is an NSArray
objectForKey:#"categoryName"] stringForKey:#"text"];
// This breaks NSArray doesn't respond to objectForKey:
Breaking it down a bit, you need:
NSDictionary* categorys = [xmlDictionary objectForKey:#"Categorys"];
NSArray* categoryArray = [categorys objectForKey: #"Category"];
NSDictionary* category = [categoryArray objectAtIndex: i]; // i is the index of the category you want e.g. 0
// etc
The answer is in the error message. One of the objects that you are getting from
NSString *category = [[[[xmlDictionary objectForKey:#"Categorys"] objectForKey:#"Category"] objectForKey:#"categoryName"] stringForKey:#"text"];
Doesn't have the selector objectForKey.
Now you need to break down your code and do some debugging to find out where you are going wrong.
Was getting the same error "[NSCFArray objectForKey:]: unrecognized selector sent to instance"
When I looked at the structure of my plist file that was loaded from the bundle at runtime, it did not seem possible that I was using the wrong selectors. The problem is that when I ran the app, it was not pulling the original plist from the bundle, it was pulling a saved plist from my apps directory. Because the saved plist had an incorrect, and completely different structure than my original plist, I indeed was using the wrong selectors.

How Do You DO A Plist Array Display with iPhone?

I have looked high and low for sample Plist display code and can't seem to find any that does what I want to do. I know it can't be too hard, but I am new to Plists.
I have the following Array in a Plist and I can't seem to get the right command to display the information. Am I doing something wrong in my Plist setup? It compiles fine but no Data gets to the iPhone Simulator.
What would be the normal way of displaying the info?
I have a condition set:
If condition one
then display "+0+1"
else
display "+0+2"
*What I am hoping it to display is:
* "this is one"
* "this is two"
* "this is three"
* else display
* "555-555-1234"
* "555-555-0000"
* "555-555-5555"
MY PLIST IS AS FOLLOWS
*
Key Type Value
*Root Dictionary (2 items)
*+0+1 Array (3 items)
*Item 0 String "this is one"
*Item 1 String "this is two"
*Item 2 String "this is three"
*+0+2 Array (3 items)
*Item 0 String "555-555-1234"
*Item 1 String "555-555-0000"
*Item 2 String "555-555-5555"
*
// read property list into memory as an NSData object
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
NSString *errorDesc = nil;
NSPropertyListFormat format;
// convert static property list into dictionary object
NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];
// assign values
self.item1 = [temp objectForKey:#"name1"];
self.item2 = [NSMutableArray arrayWithArray:[temp objectForKey:#"name2"]];
// display values
bigCheese.text = disp1;
numberZero.text = [disp2 objectAtIndex:0];
numberOne.text = [disp2 objectAtIndex:1];
numberTwo.text = [disp2 objectAtIndex:2];
Once you get a dictionary get all values for that dictionary. In your case, get all values from the temp dictionary. It should return you an array containing two arrays.
NSArray *valueArray = [temp allValues];
Now you have two arrays and if you want to access "555-555-5555", do like this:
[[valuesArray objectAtIndex:1] objectAtIndex:2];
Or if you are sure that "name1" and "name2" are the keys of your dictionary you can access it this way:
[[temp objectForKey:#"name1"] objectAtIndex:2];
Once you get this info then it is up to you to decide how you want to display it. I suggest you to DEBUG and see if the dictionary and array objects are created properly first. Not sure what are those disp1 and disp2 in the sample code you posted..
Try using:
NSString *file = [[NSBundle mainBundle] pathForResource:#"Data" ofType:#"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:file];
NSArray *array = [dict objectForKey:#"Array"]; NSLog(#"%#", array);
It's simple, so less chances to do something wrong.