#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
не сохраняет его, поэтому он может быть удален из вашего массива при его выпуске.