僵尸对象或许对很多人听起来很恐怖、也很陌生,如果要说起EXEC_BAD_ACCESS异常,可能大家并不陌生。试图调用僵尸对象方法应用会崩溃(应用直接跳出),并抛出异常EXEC_BAD_ACCESS。
我们看看代码ViewController的代码片段:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger row = [indexPath row];
NSDictionary *rowDict = [self.listTeams objectAtIndex:row];
NSString *rowValue = [rowDict objectForKey:@"name"];
NSString *message = [[NSString alloc] initWithFormat:@”您选择了%@队。”, rowValue];
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@”请选择球队”
message:message
delegate:self
cancelButtonTitle:@”Ok”
otherButtonTitles:nil];
[alert release]; ①
[message release];
[alert show]; ②
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
注意看程序代码的黑体部分,你会发现什么问题吗?程序运行的结果抛出EXEC_BAD_ACCESS异常。假设我们现在无法找到问题,可以使用Instruments工具的Zombies跟踪模板。其中Instruments选择Zombies模板,点击Profile按钮就可以进入了。
点击Allocations的“i”按钮,弹出Target菜单配置Zombies模板,在Launch Configuration中勾选Record reference counts和Enable NSZombie detection。其中Record reference counts是显示引用计数,Enable NSZombie detection是能够检测僵尸对象。
这样在程序运行的时候,如果发现僵尸对象它就会弹出一个对话框,点击其中“→”按钮,在屏幕的下方会显示僵尸对象的详细信息。
僵尸对象为UIAlertView类型,从上到下僵尸对象是引用计数的变化是:创建 → 释放 → 僵尸化。打开扩展详细视图,在右边的跟踪堆栈信息进入我们程序代码,会打开对应代码,定位僵尸对象。
在上面的3条高亮显示的代码会影响对象引用计数,从中我们不难发现问题。关于解决方案就本例而言需要将代码②行的显示警告框的[alert show]语句,放在[alert release]语句之前调用就可以了。这就是僵尸对象问题。