Dictionary Getting Released? - iphone

Currently, I have a class that is parsing XML and sending the dictionary that the XML is parsed to to a view controller.
Here is a snippet of the code that sends the dictionary to the other class (where "response" is the dictionary):
if ([elementName isEqualToString:#"SessionData"])
{
// We reached the end of the XML document
// dumps dictionary into log
NSLog(#"Dump:%#", [response description]);
// sends dictionary to the VC
CardSetupViewController *setup = [[CardSetupViewController alloc]init];
setup.response = self.response;
//checks
NSLog(#"%# lololololol", [setup.response description]); //THIS WORKS FINE!!
return;
}
At that point, the code works fine. That NSLog marked with //THIS WORKS FINE!! works... obviously. Here is the method in the ViewController:
- (BOOL)authorize //this
{
AddCard *addCard = [[AddCard alloc]init];
ServerConnection *connection = [[ServerConnection alloc]init];
//XMLParser *xmlParser = [[XMLParser alloc]initXMLParser];
//serverReturn posts the data and is the ACTUAL server response in NSData form
NSData *serverReturn = [connection postData:[addCard textBoxToXml:
[self nameOnCardGet]:
[self ccNumGet]:
[self expMoGet]:
[self expYrGet]:
[self cvvGet]:
[self zipGet]:
[self nickNameGet]:
[self pinGet]]];
//This takes the information from the server and parses it to "response"
//Creates and inits NSXMLParser Object
NSXMLParser *nsXmlparser = [[NSXMLParser alloc] initWithData:serverReturn];
//Create and init our delegate
XMLParser *parser = [[XMLParser alloc] initXMLParser];
//set delegate
[nsXmlparser setDelegate:(id <NSXMLParserDelegate>) parser];
//initiates self.response THIS MAY NOT BE NEEDED
//response = [[NSMutableDictionary alloc]init];
//parsing
BOOL success = [nsXmlparser parse];
//error catch testing
if (success) {
NSLog(#"No errors");
}
else {
NSLog(#"Error parsing document!");
}
//dump
NSLog(#"ZOMG CHECK DIS OUT%#", [response description]);
return NO;
}
Basically, the NSLog that states "ZOMG CHECK DIS OUT" is returning (null) and I can't figure out why. No compilation errors, it is a property/synthesize as well. Any ideas?
Thanks in advance. Oh, and please excuse my NSLog comments. I had to differentiate from different parts of the code, and I was in a good mood.
Edit: I am using Automatic Reference Counting. Don't worry, nothing is leaking.

In your first code block, you generate a CardSetupViewController and then leak it. It is unrelated to whatever object is running the second code block. I assume that your second view controller is from your NIB?
Note that you're also leaking your NSXMLParser.

Your [response description], whatever that is, is probably an autoreleased object that gets released before ZOMG CHECK DIS OUT. Retain it and see if that works. Don't forget to release it when you're done with it.

Related

Memory Management Issue with copy in connectionDidFinishLoading

I am passing the _resultArray object which is in connectionDidFinishLoading using delegate from one class to another class through this delegate method.I am releasing in dealloc but i am not sure that it is ok.How to release this _resultArray..
Here is my code..
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
NSString *urlDataString = [[NSString alloc]initWithData:receiveData
encoding:NSUTF8StringEncoding];
NSMutableDictionary *soapDictionary = nil;
soapDictionary = [parser objectWithString:urlDataString error:&error];
resultArray = [soapDictionary copy];
[urlDataString release];
[self soapResultSurvey:resultArray];
}
//Delegate Method
-(void)soapResultSurvey:(id)_resultSurvey{
[delegate soapResultSurvey:_resultSurvey];
}
resultArray = [[soapDictionary copy] autorelease];
then remember that resultArray will be deallocated later at the end of the thread, so if your delegate need to retain it, well, do it there, in your delegate soapResultSurvey: method

NSXMLParser crashing on faulty xmls, no correct error handling?

Anyone else experiencing crashes deep down in the iPhone libraries when NSXMLParser parses an xml containing errors? I thought it was supposed to call:
(void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
but instead it crashes the entire app somewhere inside _xmlRaiseError.
Is anyone else experiencing this and is there a way to catch this, instead of having my program crash?
The error handling is not found in the TouchXML framework or in the CXMLDocument. It is in the libxml framework which will (to my knowledge) output a string but not raise an exception. So it is all about passing an error pointer and then reading it straight after. If it is not nil, an error has occurred. If you are getting crashes the error should be somewhere else... Hope that helps.
You should be able to use #try/#catch to wrap this if you need to handle all kinds of malformed XML.
The XML parser never crashes for me, but my handlers have crashed on occasion. For example if I get < foo /> and try to store the value of it in an array (nil, boom). The following is the exact code I use, which parses XML using a delegate that I've made.
NSData *data = [[NSData alloc] initWithContentsOfFile:filename];
NSXMLParser *xmlParser = [[NSXMLParser alloc] initWithData:data];
MGXMLParser *parser = [[MGXMLParser alloc] initWithRecipient:self];
[xmlParser setDelegate:parser];
BOOL success = [xmlParser parse];
if (success) {
NSLog(#"No errors");
} else {
NSError *error = [xmlParser parserError];
NSLog(#"Errors with xmlParser: %#", [error localizedDescription]);
}
[parser release];
[xmlParser release];
[data release];
MGXMLParser is my own class which is a delegate for the XML parser, in case it wasn't obvious.
Update: oops, SO parsed my < foo/ > into nothingness.
The problem is probably that your XML string gets autoreleased before parseErrorOccurred ever gets called, causing a call to a dealloc'd object.
The solution is do to something like:
NSData *data = [[contentString dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES] retain]; //use a retain, to stop data being autoreleased
NSXMLParser* xmlParse = [[NSXMLParser alloc] initWithData:data];
[xmlParse setDelegate:self];
[xmlParse parse];
[data release]; //now release data
[xmlParse release];
I filed this as a bug report and Apple answered me 1 year later to say it should be fixed in iOS5.

how to know when to release string for iphone

i have this
NSXMLParser *xmlParserf = [[NSXMLParser alloc] initWithContentsOfURL:url];
// NSLog(#"URL%#",urlf);
//Initialize the delegate.
XMLParser *parserf = [[XMLParser alloc] initXMLParser];
[xmlParserf setDelegate:parserf];
//Start parsing the XML file.
BOOL successs = [xmlParserf parse];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSLog(#" this xml is %d",[xmlParserf retainCount]);// getting error
NSLog(#" this paaat is %d",[parserf retainCount]);// getting error
if(successs)
{
NSLog(#"ZONE IS PARSED");
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
else
{
NSLog(#"NOT PARSED!!!");
}
//[xmlParserf release]; not working
//[parserf release];
now i dont know when to release those objects these are running in some threads
everytime you alloc (or copy), you must either release or autorelease.
In this case:
NSXMLParser *xmlParserf = [[[NSXMLParser alloc] initWithContentsOfURL:url] autorelease];
and
XMLParser *parserf = [[[XMLParser alloc] initXMLParser] autorelease];
It means that you keep it in memory at least until the end of the current function. If other objects hang on to it (i.e. retain it) then the objects stay in memory, until they are released (by those other objects).

iPhone: Parsing multiple XML with NSXMLParser in background disturbing each other

I have a strange issue, when it comes to parsing XML with NSXMLParser on the iPhone. When starting the app, I want to preload 4 table-views, that are populated by RSS-Feeds in the background.
When I init the table-views one-by-one, than loading, parsing and displaying all works like a charm. But when I try to init all view at once (at the same time), than it seems, that the XML-parser-instances are disturbing each other. Somehow data from one XML-Feed are "broadcasted" into other xml-parser instances, where they do not belong. Example: there is a "teammember" item, with "This is my name". When this bug occurs, there is a string from another xml-feed added, i.e. resulting in: "This is my name58", where 58 is the chart-position of something from the other view. "58" seems to miss then on the other instance.
It looks to me, that this bug occurs because of the NSXMLParser-delegate method:
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
if (!currentStringValue) {
currentStringValue = [[NSMutableString alloc] initWithCapacity:50];
}
[currentStringValue appendString:string];
}
In this case "by coincidence" bytes are appended to strings, where they do not belong to.
The strange thing is, that every instance of NSXMLParser is unique, got its own unique delegates, that are attached to their own ViewController. Every parsing-requests spawns it own background-task, with its own (also also unique named) Autorelease-pool.
I am calling the NSXMLParser like this in the ViewController:
// prepare XML saving and parsing
currentStringValue = [[[NSMutableString alloc] initWithCapacity:50] retain];
charts = [[NSMutableArray alloc] init];
NSURL *url = [[NSURL alloc] initWithString:#"http://(SOME XML URL)"];
xmlParser = [[[NSXMLParser alloc] initWithContentsOfURL:url] retain];
//Set delegate
[xmlParser setDelegate:self];
//loading indicator
progressWheel = [[[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(150.0,170.0,20.0,20.0)] autorelease];
progressWheel.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
[self.view addSubview:progressWheel];
[progressWheel startAnimating];
// start loading and parsing the xml-feed in the background
//[self performSelectorInBackground:#selector(parse:) withObject:xmlParser]; -> I also tried this
[NSThread detachNewThreadSelector:#selector(parse:) toTarget:self withObject:xmlParser];
And this is one of the background-tasks, parsing the feed:
-(void)parse:(NSXMLParser*)myParser {
NSAutoreleasePool *schedulePool = [[NSAutoreleasePool alloc] init];
BOOL success = [myParser parse];
if(success) {
NSLog(#"No Errors. xmlParser got: %#", myParser);
(POST-PROCESSING DETAILS OF THE DATA RETURNED)
[self.tableView reloadData];
} else {
NSLog(#"Couldn't initalize XMLparser");
}
[progressWheel stopAnimating];
[schedulePool drain];
[myParser release];
}
What could cause this issue? Am I calling the background-task in the right way? Why is this bug approaching, since every XML-Parser got its own, unique instance?
You should not be updating UI elements (like progressWheel) from inside a background thread. UI updates should be done on the main thread.
Use -performSelectorOnMainThread:withObject:waitUntilDone: to update UI elements from within a background thread.
I've released an open source RSS/Atom Parser for iPhone and it makes reading and parsing web feeds extremely easy.
You can set it to download the data asynchronously, or you could run it in a background thread synchronously to collect the feed data.
Hope this helps!

XMLParser delegate and memory leaks

I am building an application that has to handle the parsing of several different kinds of XML files. As I want to standardize the procedure as much as possible, I created a singleton class which handles the parsing of any XML data. The class is handed two options, a unique identifier telling it what kind of XML data it is going to parse and the data itself. Within the class, there is the following function which does the parsing and returns an NSMutableArray object containing the results:
- (NSMutableArray*) initAPIDataParse:(NSData *)data APIRequestType:(int)requestType {
// Init parser
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
// Set delegate for parser
if (requestType == kXMLParserTypeOne) {
[parser setDelegate:[[[XMLParserOne alloc] init] autorelease]];
} else if (requestType == kXMLParserTypeTwo) {
[parser setDelegate:[[[XMLParserTwo alloc] init] autorelease]];
} // etc.
// let's parse the XML
[parser parse];
[parser release];
return lastParsedDict; //lastParsedDict is the NSMutableArray object returned from the Parser delegate
}
Above code works like a charm, except that if you parse the same type of XML multiple times this line leaks (which makes sense):
[parser setDelegate:[[[XMLParserOne alloc] init] autorelease]];
I have tried several things to resolve this issue like creating an instance variable with an instance of the delegate and releasing it whenever the same type of XML Parser was asked for again, yet it didn't work.
I am glad for any help here, thanks a lot!
Delegates objects are never retained. So using an auto-released object for them is mostl likely going to end up in a crash.
I refactored your code:
- (NSMutableArray*) parseData: (NSData*) data withAPIRequestType: (int) requestType
{
NSMutableArray* result = nil;
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
if (parser != nil)
{
switch (requestType) {
case kXMLParserTypeOne:
delegate = [XMLParserOne new];
break;
case kXMLParserTypeTwo:
delegate = [XMLParserTwo new];
break;
}
if (delegate != nil)
{
[parser setDelegate: delegate];
[parser parse];
result = [delegate.result retain];
[delegate release];
}
[parser release];
}
return [result autorelease];
}