Need help with NSXMLPaser tutorial - iphone

At the last part of the tutorial I am having an issue with the users variable, its saying users variable is undeclared.
It is being declared in my NSXMLPaser class that I created as a NSMutableArray and I am "#import"ing the header file of NSXMLPaser class...
Here is the link to the tutorial I am working through, any help would be greatly appreciated.
http://wiki.cs.unh.edu/wiki/index.php/Parsing_XML_data_with_NSXMLParser
- (void) doParse:(NSData *)data {
NSString * filePath = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"xml"];
NSData * fileData = [NSData dataWithContentsOfFile:filePath];
// create and init NSXMLParser object
NSXMLParser *nsXmlParser = [[NSXMLParser alloc] initWithData:fileData];
// create and init our delegate
XMLParser *parser = [[XMLParser alloc] initXMLParser];
// set delegate
[nsXmlParser setDelegate:parser];
// parsing...
BOOL success = [nsXmlParser parse];
// test the result
if (success) {
NSLog(#"No errors - user count : %i", [parser [users count]]); // users undeclared error here
// get array of users here
// NSMutableArray *users = [parser users];
} else {
NSLog(#"Error parsing document!");
}
[parser release];
[nsXmlParser release];
}

Either you use "[parser.users count]" like Babji said or you could use the dot notation for everything, like "parser.users.count".
Also, you could use "[[parser users] count]". This means you first get the collection users of the parser ("[parser users]") and then you call count on that collection ("[[parser users] count]").

use the users variable [parser.user count]

Related

Why NSMutableDictionary don't want write to file?

- (void)viewDidLoad
{
[super viewDidLoad];
if ([[NSFileManager defaultManager] fileExistsAtPath:pathString])
{
infoDict = [[NSMutableDictionary alloc] initWithContentsOfFile:pathString];
}
else
{
infoDict = [[NSMutableDictionary alloc]initWithObjects:[NSArray arrayWithObjects:#"BeginFrame",#"EndFrame", nil] forKeys:[NSArray arrayWithObjects:[NSNumber numberWithBool:YES],[NSNumber numberWithBool:YES], nil]];
if ([infoDict writeToFile:pathString atomically:YES])
{
NSLog(#"Created");
}
else
{
NSLog(#"Is not created");
NSLog(#"Path %#",pathString);
}
}
This is my code. I check if file is created, if not - I create a NSMutableDictionary and I write it to file at path, but writeToFile method returns NO. Where is problem? If I create this file with NSFileManager it works, but doesn't when I want to write a dictionary.
writeToFile:atomically only works if the dictionary you call it on is a valid property list object (see docs).
For a NSDictionary to be a valid property list object, among other things, its keys must be strings, but in your example the keys are NSNumber instances.
You can not control the content you are going to write sometimes. For example, you can't avoid a null value when you are going to write a JSON object that is gotten from a server.
NSData is compatible with these "invalid" values, so converting NSArray or NSDictionary to NSData is an ideal way in these cases.
write:
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:jsonObject];
[data writeToFile:path atomically:YES];
read:
NSData *data = [NSData dataWithContentsOfFile:path];
NSDictionary *jsonObject = [NSKeyedUnarchiver unarchiveObjectWithData:data];

Solution for a leak in touchXML when no internet and using initWithContentsOfURL

There's a leaking CXMLDocument object shown in instruments everytime, a request to an XML is made to a webservice AND when there's no internet connection available. Here's my code:
NSString *path = ... some URL
NSURL *url = [NSURL URLWithString: path];
CXMLDocument *itemListParser; = [[CXMLDocument alloc] initWithContentsOfURL:url options:0 error:nil];
... other stuff ...
If we digg deeper and trace initWithContentsOfURL call then we will find this method in "CXMLDocument.m":
- (id)initWithContentsOfURL:(NSURL *)inURL encoding:(NSStringEncoding)encoding options:(NSUInteger)inOptions error:(NSError **)outError
{
if (outError)
*outError = NULL;
NSData *theData = [NSData dataWithContentsOfURL:inURL options:NSUncachedRead error:outError];
if (theData)
{
self = [self initWithData:theData encoding:encoding options:inOptions error:outError];
}
else
{
[self release]; //My suggested fix: We need to release an alloc'ed object because after the "self = null" it will be unable to release it. See the info below.
self = NULL;
}
return(self);
}
It appears, if theData is nil (for example no connection) then self will be nil, and so the result of the call to TouchXML initWithContentsOfURL will be nil too. So, in my code:
CXMLDocument *itemListParser; = [[CXMLDocument alloc] initWithContentsOfURL:url options:0 error:nil];
I'm alloc'ing a memory but init returns nil, and so itemListParser becomes nil too. So later, trying to release the parser with [itemListParser release] does nothing because release is send to nil.
I was able to fix a leak by adding "[self release]" before "self = NULL" (see the line with my comment in TouchXML initWithContentsOfURL method)

unrecognized selector

I have a problem with the next code:
NSDictionary * imagen = [[NSDictionary alloc] initWithDictionary:[envio resultValue]];
NSString *imagenS = [imagen valueForKey:#"/Result"];
ClaseMaestra *b1 = [[ClaseMaestra alloc]init];
NSData *imagenDecode = [[NSData alloc] initWithData:[b1 base64DataFromString:imagenS]];
NSLog(#"Decode Image:");
NSLog(#"%#", imagenDecode);
//SAVE IMAGE
NSArray *sysPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *docDirectory = [sysPaths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:#"%#david.png",docDirectory];
[imagenDecode writeToFile:filePath atomically:YES];
Blockquote
[envio resultValue] --> return a NSDictionary with one image in Base 64 codification.
I want decoder and save this image but in my console I have showed this message:
2011-08-23 19:19:39.750 WSStub[38501:a0f] *************************
2011-08-23 19:19:39.752 WSStub[38501:a0f] SendImage
2011-08-23 19:19:39.752 WSStub[38501:a0f] *************************
2011-08-23 19:19:39.759 WSStub[38501:a0f] -[ClaseMaestra base64DataFromString:]: unrecognized selector sent to instance 0xd00ad0
Program received signal: “EXC_BAD_ACCESS”.
ClaseMaestra interface is:
#import <Foundation/Foundation.h>
#class NSString;
#interface ClaseMaestra : NSObject
+ (NSMutableData *)base64DataFromString: (NSString *)string;
#end
I can´t understand the "unrecognized selector" error...
This is a class method and you call iton an instance of the class. You should either change it to an instance method. instead of:
+ (NSMutableData *)base64DataFromString: (NSString *)string;
Use:
- (NSMutableData *)base64DataFromString: (NSString *)string;
Or, change the call, instead of:
NSData *imagenDecode = [[NSData alloc] initWithData:[b1 base64DataFromString:imagenS]];
Use:
NSData *imagenDecode = [[NSData alloc] initWithData:[ClaseMaestra base64DataFromString:imagenS]];
What to choose depends on your needs.
base64DataFromString: is a class method (starts with a +). So instead of
ClaseMaestra *b1 = [[ClaseMaestra alloc]init];
NSData *imagenDecode = [[NSData alloc] initWithData:[b1 base64DataFromString:imagenS]];
You should do
NSData *data = [ClaseMaestra base64DataFromString:imagenS];
You are sending a class message to an instance. The receiver should be a class.
So do:
NSData *imagenDecode = [[NSData alloc] initWithData:[ClaseMaestra base64DataFromString:imagenS]];
You'll also get this error if you use the name of a private framework, eg: MPMovieView .Everyone knows you're not supposed to use those, but what I didn't know is that I was using one!
What's odd is, if you use Xibs, they load the system one and give you the same type of error (Class methods).
But if you load it in code, it shadows the system framework one. I spent a decent hour scratching my head, ensuring everything was hooked up right... it was, just needed to change how I named my custom stuff. Posting this for anyone with similar

Cast JSON object (NSCFDictionary) to string and parse it

I'm working with facebook connect and trying to handle the JSON object that i'm receiving.
I invoked the requstWithGraphPath method and need to get back a JSON object,
tried to parse it and getting an error:
SBJSON *parser = [[SBJSON new] autorelease];
NSData *data = [[NSData alloc] initWithData:result];
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; -> in this line - "[__NSCFDictionary length]: unrecognized selector sent to instance"
NSArray *events = [parser objectWithString:jsonString];
What's the problem?
Can I get the string in an other way or parse the object differently?
Thanks.
If you are working with the delegate callback
- (void)request:(FBRequest *)request didLoad:(id)result;
the parsing work has been done for you. Traverse the NSDictionary or NSArray to find the data you are looking for. If you are working with the delegate callback
- (void)request:(FBRequest *)request didLoadRawResponse:(NSData *)data;
you should initialize an NSString with the data, and use the category method that SBJSON adds to NSString for creating an id. That is assuming the data is data that constructs a string.
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
id result = [jsonString JSONValue];
Are you sure the error happens on that line, or does it happen on the line above?
If result is an NSDictionary (or CFDictionary, same thing), then it is already parsed and you do not need to do that yourself — and it could cause that error message too, on the line above.
The line:
data = [[NSData alloc] initWithData:result];
is almost certainly not what you want to do, as it is equivalent to
data = [result copy];
assuming that result is an NSData object (or NSMutableData), which I'm guessing it isn't.

Parsing JSON to get Google Reader Label information

I am trying to make a google reader app. I am able to get the subscription list in JSON format like this:
{"subscriptions":[{"id":"feed/http://aspn.activestate.com/ASPN/Cookbook/Python/index_rss","title":"ActiveState Code: Python recipes","categories":[{"id":"user/014533032765194560dwd0/label/Programming","label":"Programming"}],"sortid":"E6312EFB","firstitemmsec":"1258141669516","htmlUrl":"http://code.activestate.com/recipes/langs/python/"},
I am interested in getting the label value (in the above case "Programming") into an array. Here is my current code:
-(BOOL)parsedSuccess {
SBJsonParser *parser = [[SBJsonParser alloc]init];
if (!receivedData) {
[self getSubscriptionList:GOOGLE_READER_SUBSCRIPTION_LIST];
}
NSMutableString *body = [[NSMutableString alloc]initWithData:receivedData encoding:NSUTF8StringEncoding];
if (body) {
NSArray *feeds = [parser objectWithString:body error:nil];
NSDictionary *results = [body JSONValue];
NSArray *subs = [results valueForKey:#"subscriptions"];
NSString *subTitles;
for (NSDictionary *title in subs){
subTitles = [title objectForKey:#"categories"];
NSLog(#"%#",subTitles);
}
}
return YES;
}
Can someone help me in getting the label values?
[[[[[result valueforkey:#"subscription"]objectatindex:0]valueforkey:#"categories"]objectatindex:intvalue]valueforkey:#"label"];
I just helped to make logic. Be sure to check for spelling mistakes before implementing.