Varundroid
Varundroid

Reputation: 9234

iOS - Unable to access NSMutableArray in didSelectRowAtIndexPath?

I am unable to access my NSMutableArray in didSelectRowAtIndexPath although i am able to access it in cellForRowAtIndexPath.

Here is my code :-

- (void)viewDidLoad
{
    NSString *path = [[NSBundle mainBundle] pathForResource:@"drinks" ofType:@"plist"];
    self.drinkArray = [[NSMutableArray alloc] initWithContentsOfFile:path];
    NSLog(@"%@", self.drinkArray);
    [super viewDidLoad];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    NSLog(@"I am inside cellForRowAtIndexPath");
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    // Configure the cell.
    NSDictionary *dict = [self.drinkArray objectAtIndex:indexPath.row];
    cell.textLabel.text = [dict objectForKey:@"name"]; 
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    [dict release];
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    DrinkDetails *detailViewController = [[DrinkDetails alloc] initWithNibName:@"DrinkDetails" bundle:nil];
    // ...
    // Pass the selected object to the new view controller.
    //detailViewController.drink = [self.drinkArray objectAtIndex:indexPath.row];

    NSLog(@"%@", self.drinkArray);

    [self.navigationController pushViewController:detailViewController animated:YES];
    [detailViewController release];

}

Sometime NSLog prints some stupid output and sometime it gives me an error "EXC_BAD_ACCESS".

Please take a look and check what is wrong with my code.

Any help would be appreciated.

Thanks.

Upvotes: 0

Views: 983

Answers (3)

zaph
zaph

Reputation: 112855

Don't release an object unless it was created with alloc or obtained with a method beginning with new or copy or explicitly retain'ed. (NARC)

In this case:

NSDictionary *dict = [self.drinkArray objectAtIndex:indexPath.row];

was not returned retained so you do not have ownership and should not release it.

By the same token:

self.drinkArray = [[NSMutableArray alloc] initWithContentsOfFile:path];

is alloc'ed so it needs to be released or obtained with a convince method that will return an autoreleased object:

self.drinkArray = [NSMutableArray arrayWithContentsOfFile:path];

Upvotes: 2

Jacob Relkin
Jacob Relkin

Reputation: 163288

You have one (really two) issues, but the main one is in your -cellForRowAtIndexPath: method:

[dict release];

Get rid of this line and it should work just fine.

The reason why this fixes your issue is because -objectAtIndex: simply returns a pointer to the requested object in memory, therefore you do not (and should not) send the -release message to that object because the NSArray obtained ownership of the object when it was inserted. Sending -release to this object reference effectively deallocates the object in memory and now this indice in the NSArray is pointing to garbage memory. BAD BAD BAD

The other issue is that you have a memory leak here:

self.drinkArray = [[NSMutableArray alloc] initWithContentsOfFile:path];

You are sending the -retain message to an object reference that you already have ownership of by way of sending -alloc. (This of course assumes that your @property has the retain setter modifier)

To fix this issue, simply send the -autorelease message to this instance:

self.drinkArray = [[[NSMutableArray alloc] initWithContentsOfFile:path] autorelease];

Upvotes: 3

tobiasbayer
tobiasbayer

Reputation: 10379

You shouldn't [dict release]in cellForRowAtIndexPath. objectAtIndex does not retain it, so it may be sweeped out of your array when you release it.

Upvotes: 1

Related Questions