从 UITableView 委托方法中访问实例变量时获取“EXC_BAD_ACCESS”

Posted

技术标签:

【中文标题】从 UITableView 委托方法中访问实例变量时获取“EXC_BAD_ACCESS”【英文标题】:Getting “EXC_BAD_ACCESS” when accessing instance variable from within UITableView delegate method 【发布时间】:2009-09-20 02:07:26 【问题描述】:

我的 iPhone 应用程序在从 UITableView 委托方法之一访问实例变量时崩溃了。我想我会保留它,所以我不明白为什么我无法毫无问题地访问它。

这是我的 .h 文件

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

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

@property (nonatomic, 保留) NSDictionary *alerts; @property (nonatomic, 保留) 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];
 

【问题讨论】:

【参考方案1】:

对于任何 EXC_BAD_ACCESS 错误,您通常会尝试向已释放对象发送消息。 最佳方法是使用NSZombieEnabled。

这是通过从不实际释放对象来实现的,而是将其包装为“僵尸”并在其中设置一个标志,表明它通常会被释放。这样,如果您再次尝试访问它,它仍然会在您出错之前知道它是什么,并且通过这些信息,您通常可以回溯以查看问题所在。

当调试器有时会发现任何有用的信息时,它尤其有助于后台线程。

非常重要的注意事项但是,您需要 100% 确保这仅在您的调试代码中,而不是在您的分发代码中。因为从来没有发布过任何东西,所以你的应用程序会泄漏、泄漏和泄漏。为了提醒我这样做,我把这个日志放在我的 appdelegate 中:

if(getenv("NSZombieEnabled") || getenv("NSAutoreleaseFreedObjectCheckEnabled"))
  NSLog(@"NSZombieEnabled/NSAutoreleaseFreedObjectCheckEnabled enabled!");

【讨论】:

【参考方案2】:

我假设您已经检查了发出警报的设置。如果您尝试在 nil 引用上调用 [alerts objectForKey:],则会收到该错误。

【讨论】:

【参考方案3】:

问题出在我设置警报的方式上。我没有使用会保留对象的 setter 方法,而是无知地这样做了:

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

正如我猜想的那样,编译时没有任何警告或错误。

通过使用setter,

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

我必须创建,警报被“保留”,因为它需要,一旦视图控制器加载,一切都很好。

我对 Objective-C 非常陌生,不得不搞乱内存管理,但在使用它和 iPhone SDK 大约 4 周后,我终于开始看到曙光了。

【讨论】:

以上是关于从 UITableView 委托方法中访问实例变量时获取“EXC_BAD_ACCESS”的主要内容,如果未能解决你的问题,请参考以下文章

从 prepareForSegue:sender 设置 UITableView 委托和数据源时出错:

将 UITableView 委托和数据源从 tableViewController 中分离出来

如何从 UIViewController 传递变量来委托 UITableViewController

为啥我们需要 ios 中 UITABLEVIEW 的数据源和委托方法 [重复]

从自定义单元格访问父视图

类库和委托以及万能变量