iOS开发那些事-性能优化–查找和解决僵尸对象
内存泄漏是当一个对象或变量在使用完成后没有释放掉,那么如果我们走了另外一个极端情况会什么样呢?这就导致过渡释放(over release)问题,从而使对象“僵尸化”,对象称为僵尸(zombies)对象。一个对象已经被释放过了,或者调用者没有这个对象的所有权而释放它,都会造成过渡释放,产生僵尸对象。
僵尸对象或许对很多人听起来很恐怖、也很陌生,如果要说起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]语句之前调用就可以了。这就是僵尸对象问题。