0

I'm a newbie to Objective-C & iPhone development, hence please bear with me.

I'm working on an app which loads with UITableView and upon selecting one particular cell called "Address Book" it should load with another UITableView containing all the addresses retrieved from a web request. Using NSXMLParser's delegate methods I'm storing those addresses into a NSMutableArray defined in the loaded view's header file. But the problem occurs when those addresses are being displayed onto the UITableView cells (yes, I have got the count for the number of cells). Can anybody please help me with this problem? I'm stuck on this for days now !!! Following is my code:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}

AddressEntry *entry = (AddressEntry *)[self.addresses objectAtIndex:indexPath.row];

@try
{
    NSLog(@"%@", entry.firstName);
}
@catch (NSException * e) 
{
    @try 
    {
        NSLog(@"%@", entry.lastName);
    }
    @catch (NSException * e) 
    {
        NSLog(@"%@", entry.lastName);
    }
}
[entry release];

return cell;
}

    - (void)parserDidStartDocument:(NSXMLParser *)parser
{
    self.currentElement = nil;
    self.f_Name = nil;
    self.l_Name = nil;
    self.phone = nil;
    self.email = nil;
    count = 0;
    self.addresses = [[NSMutableArray alloc] init];
}

- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName 
                                     namespaceURI:(NSString *)namespaceURI 
                                    qualifiedName:(NSString *)qName 
                                       attributes:(NSDictionary *)attributeDict
{


if([elementName isEqualToString:@"Entries"])
    {
        count = [[attributeDict valueForKey:@"total"] intValue];
    }
    else if([elementName isEqualToString:@"FirstName"])
    {       
        [self.f_Name release];
        self.f_Name = [[NSString alloc] init];
    }
    else if([elementName isEqualToString:@"LastName"])
    {
        [self.l_Name release];
        self.l_Name = [[NSString alloc] init];
    }
    else if([elementName isEqualToString:@"PhoneNumber"])
    {
        [self.phone release];
        self.phone = [[NSString alloc] init];
    }
    else if([elementName isEqualToString:@"EmailAddress"])
    {
        [self.email release];
        self.email = [[NSString alloc] init];
    }
    else if([elementName isEqualToString:@"Record"])
    {
        [self.addrEntry release];
        self.addrEntry = [[[AddressEntry alloc] init] retain];
    }

[self.currentElement release];
self.currentElement = nil;
self.currentElement = [elementName copy];
}


- (void) parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName 
                                       namespaceURI:(NSString *)namespaceURI 
                                      qualifiedName:(NSString *)qName
{
    //
    if([elementName isEqualToString:@"FirstName"])
        self.addrEntry.firstName = self.f_Name;
    else if ([elementName isEqualToString:@"LastName"])
        self.addrEntry.lastName = self.l_Name;
    else if([elementName isEqualToString:@"PhoneNumber"])
        self.addrEntry.mobile = self.phone;
    else if([elementName isEqualToString:@"EmailAddress"])
        self.addrEntry.emailAddress = self.email;
    else if([elementName isEqualToString:@"Record"])
    {
        [self.addresses addObject:self.addrEntry];
        [self.addrEntry release];
        self.addrEntry = nil;
        /*AddressEntry *e = (AddressEntry *)[self.addresses lastObject];
        NSLog(@"%@ %@ %@ %@", e.firstName, e.lastName, e.mobile, e.emailAddress);
        [e release];*/
    }
}


- (void) parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
    if([currentElement isEqualToString:@"FirstName"])
        self.f_Name = string;
    else if([currentElement isEqualToString:@"LastName"])
        self.l_Name = string;
    else if([currentElement isEqualToString:@"PhoneNumber"])
        self.phone = string;
    else if([currentElement isEqualToString:@"EmailAddress"]) 
    {
        self.email = string;
    }

}

1 Answers1

0

The most likely reason for the app crashing is this line in cellForRowAtIndexPath:

[entry release];

You did not alloc/init the variable entry there so don't call release on it. Remove that line.

In that method, entry is only holding a reference to an already-allocated object in the address array. It doesn't "own" the object so it shouldn't release it.

This page in the Apple docs shows a nice flow diagram and some simple rules for memory management that might help in understanding this better.


As a separate issue unrelated to the crashing, the use of @try/@catch in your example seems unnecessary. See this answer for an explanation.


Finally, also unrelated to the crashing, in foundCharacters, you should really be appending the string parameter to your data instead of just assigning because it's possible for that method to be called multiple times within the same value. See Handling XML Elements and Attributes for an example.

Community
  • 1
  • 1
  • Thank you very much, aBitObvious for your answer ! I, however, did that change last evening and now atleast the app doesn't crash. But that made me run into another vicious problem :-( `self.addresses` which is a `NSMutableArray` populated in the `NSXMLParser` delegate methods. When I try to access the elements of the same in UITableView's `cellForRowAtIndexPath` method, it throws an uncaught exception, which sometimes says `Variable is not a CFString` and sometimes it just gets stuck at `obj_msgsend` when I use the debugger. And sometime it just populates all the table cells with (continue..) – Kunal Patel Jan 18 '11 at 10:20
  • (continued...) the last object that was pushed into the array ! This is driving nuts to me. Could you please shed light on this ? And, thanks for your `@try\@catch` & `appendString` suggestion. I've incorporated them now. – Kunal Patel Jan 18 '11 at 10:21
  • Sorry, I think I've just resolved it now. I reckon it was `appendString` & consequently changing `self.f_Name`'s type to NSMutableString. Thanks a lot aBitObvious. – Kunal Patel Jan 18 '11 at 10:55