Получение «EXC_BAD_ACCESS» при доступе к переменной экземпляра из метода делегата UITableView - PullRequest
1 голос
/ 20 сентября 2009

Приложение iPhone разрывается, когда оно обращается к переменной экземпляра из одного из методов делегата UITableView. Я думаю, что сохраняю его, поэтому я не понимаю, почему я не могу получить к нему доступ без проблем.

Вот мой .h файл

#import <Foundation/Foundation.h>
#import "AlertSummaryCell.h"
#import "AlertDetailViewController.h"

@interface AlertSummaryTableViewController : UITableViewController {
NSDictionary *alerts;
NSString *alertKind;
}

@ property (nonatomic, retain) NSDictionary * alerts; @property (nonatomic, retain) NSString * alertKind;

@ конец

В моем .m приложение умирает при первом вызове NSLog:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSLog(@"AlertSummaryTableViewController.numberOfRowsInSection entered");
NSLog(@"  alerts description = %@", [alerts description]);
// To know how many alert summaries we have, get the value for count out of the input dictionary
int theCount = [[alerts objectForKey:@"count"] intValue];
NSLog(@"  Going to return %d",theCount);
return theCount;
}

Что мне не хватает ???

В методе viewDidLoad нет никаких проблем:

 - (void)viewDidLoad {
 NSLog(@"AlertSummaryTableViewController.viewDidLoad entered");
 NSLog(@"  alerts description = %@", [alerts description]);

 // We want the View title to include the alert count
 // To know how many alert summaries we have, get the value for count out of the input dictionary
 int theCount = [[alerts objectForKey:@"count"] intValue];

 // Now construct the title text and set our views title to it
 NSString *myTitle = [[NSString alloc] initWithFormat:@"%@ Alerts (%d)",alertKind,theCount];
 [self setTitle: myTitle];

 // Memory cleanup
 [myTitle release];

 [super viewDidLoad];
 }

Ответы [ 3 ]

4 голосов
/ 20 сентября 2009

Для любых ошибок EXC_BAD_ACCESS вы обычно пытаетесь отправить сообщение освобожденному объекту. ЛУЧШИЙ способ отследить это - использовать NSZombieEnabled .

Это работает, никогда не выпуская объект, а заключая его в «зомби» и устанавливая внутри него флаг, который говорит, что обычно он был бы выпущен. Таким образом, если вы попытаетесь снова получить к нему доступ, он все еще будет знать, что было до того, как вы допустили ошибку, и с помощью этой небольшой информации вы, как правило, можете вернуться назад, чтобы увидеть, в чем заключалась проблема.

Это особенно помогает в фоновых потоках, когда отладчик иногда выбрасывает любую полезную информацию.

ОЧЕНЬ ВАЖНО ЗАМЕЧАНИЕ однако, вам нужно на 100% убедиться, что это только в вашем отладочном коде, а не в коде дистрибутива. Поскольку ничего не выпускается, ваше приложение будет течь и течь и течь. Чтобы напомнить мне сделать это, я поместил этот журнал в моем appdelegate:

if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled"))
  NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");
0 голосов
/ 22 сентября 2009

Проблема оказалась в том, как я настраивал оповещения. Вместо того чтобы использовать метод setter, который бы сохранил объект, я по невежеству просто сделал это:

alerts = [[UIDictionary alloc] init];     // or something like this

Который скомпилирован без каких-либо предупреждений или ошибок, как я должен догадаться.

Используя сеттер,

[self setAlerts:[[UIDictionary alloc] init];   // again I'm going from memory so ...

, который я должен был создать, оповещения были «сохранены», как и должно быть, и все было хорошо, как только загрузился контроллер представления.

Я очень плохо знаком с Objective-C и мне приходится возиться с управлением памятью, но я наконец-то начинаю видеть свет после примерно 4 недель работы с ним и iPhone SDK.

0 голосов
/ 21 сентября 2009

Я полагаю, вы установили флажок для оповещения Если вы попытаетесь вызвать [alerts objectForKey:] по нулевой ссылке, вы получите эту ошибку.

...