iOS — Не удается получить доступ к NSMutableArray в didSelectRowAtIndexPath?

#iphone #ios #nsmutablearray #exc-bad-access

#iPhone #iOS #nsmutablearray #исключение -плохой доступ

Вопрос:

Я не могу получить доступ к своему NSMutableArray, didSelectRowAtIndexPath хотя я могу получить к нему доступ cellForRowAtIndexPath .

Вот мой код :-

 - (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];

}
  

Иногда NSLog выводит какой-то глупый вывод, а иногда выдает ошибку «EXC_BAD_ACCESS».

Пожалуйста, посмотрите и проверьте, что не так с моим кодом.

Любая помощь будет оценена.

Спасибо.

Ответ №1:

У вас есть одна (на самом деле две) проблемы, но основная из них заключается в вашем -cellForRowAtIndexPath: методе:

 [dict release];
  

Избавьтесь от этой строки, и она должна работать нормально.

Причина, по которой это устраняет вашу проблему, заключается в том, что -objectAtIndex: просто возвращает указатель на запрошенный объект в памяти, поэтому вы не отправляете (и не должны) -release сообщение этому объекту, поскольку NSArray получили право собственности на объект при его вставке. Отправка -release ссылки на этот объект эффективно освобождает объект в памяти, и теперь этот индекс в NSArray указывает на мусорную память. ПЛОХО, ПЛОХО, ПЛОХО

Другая проблема заключается в том, что у вас здесь утечка памяти:

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

Вы отправляете -retain сообщение на ссылку на объект, которой вы уже владеете путем отправки -alloc . (Это, конечно, предполагает, что у вас @property есть модификатор retain setter)

Чтобы устранить эту проблему, просто отправьте -autorelease сообщение этому экземпляру:

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

Комментарии:

1. В чем вторая проблема в моем коде? Я новичок в iPhone SDK, поэтому был бы признателен, если бы вы сказали мне, что еще я мог бы улучшить в этом коде. Спасибо.

Ответ №2:

Не освобождайте объект, если он не был создан alloc или получен с помощью метода, начинающегося с new или copy или явно retain ‘ed . (NARC)

В этом случае:

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

не был возвращен сохраненным, поэтому у вас нет права собственности, и вы не должны его освобождать.

Тем же токеном:

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

выделено, поэтому его необходимо освободить или получить с помощью метода convirate, который вернет автоматически выпущенный объект:

 self.drinkArray = [NSMutableArray arrayWithContentsOfFile:path];
  

Комментарии:

1. Большое спасибо за такой хороший ответ. Определенно 1 от меня.

Ответ №3:

Вы не [dict release] должны входить cellForRowAtIndexPath . objectAtIndex не сохраняет его, поэтому он может быть удален из вашего массива при его выпуске.