我创建了一个UITableView的子类,并希望将它与UITableViewController一起使用,以便在键盘出现时获得自动滚动的好处。在我的视图控制器的loadView(从UITableViewController派生)中,我执行了以下操作:
- (void)loadView
{
[super loadView];
self.tableView = [[MyCustomTableView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame style:UITableViewStyleGrouped];
self.tableView.delegate = self;
self.tableView.dataSource = self;
}
在重新分配之前,这不应该引起任何self.tableView
引用的泄漏吗?我运行Build And Analyze并没有将其报告为泄漏。
但是,如果我试着“做得好”......
- (void)loadView
{
[super loadView];
[self.tableView release];
// reassign code...
}
...当我的视图显示时,会发生各种令人讨厌的崩溃。任何人都可以向我解释简单的重新分配是否会导致泄漏,如果是这样,如何正确地做到这一点?
提前致谢。
答案 0 :(得分:1)
不,它不会导致泄漏,因为setter方法setTableView:
(在为属性分配新值时调用)将自动释放旧值。这就是属性的用途。
答案 1 :(得分:0)
正如Ole Begemann所说,当你使用点符号进行分配时,发生的事情不仅仅是简单的分配。由于setTableView:
是“保留属性”,因此它看起来像这样:
- (void)setTableView:(UITableView *)newTable
{
if(newTable != tableView) {
[tableView release];
tableView = [newTable retain];
}
}
所以你的“好”方法的问题如下。
如果您只是在tableview对象上调用release
,则表示您没有使用属性设置器,这意味着您没有将tableView设置为nil
。当你调用self.tableView = [[MyCustomTableView alloc] init...
时,当前的tableView指向一个非零的,已经解除分配的内存块。此内存块是setTableView:
将再次尝试释放的内存块,引发EXC_BAD_INSTRUCTION。
当您在某个对象上调用release
时,其指针可能会在将来重复使用,之后始终将其设置为nil
。这样您就可以将指针标记为已取消分配,并且您不会有过度释放的风险。或者只使用一个保留属性,当您将release
分配给nil
时,它会为您执行{{1}}。
答案 2 :(得分:0)
实际上你的例子会导致泄密。
self.tableView = [[MyCustomTableView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame style:UITableViewStyleGrouped];
设置self.tableView会将retain增加1,而alloc会将retain增加1。
稍后将self.tableView设置为另一个值时,保留计数减少1,保留1,因此永远不会释放分配的MyCustomTableView。
loadView
崩溃的原因是因为在您分配和添加自己之前的初始表视图已正确设置,保留为1。因此,当你释放它时,系统也会尝试释放它,但到那时它已经被释放,并且随之而来的是肮脏。
正确的方法是(自动)释放分配的MyCustomTableView
:
self.tableView = [[[MyCustomTableView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame style:UITableViewStyleGrouped] autorelease];
这样,它只有1个保留计数,当你(重新)设置self.tableView
时,它会降到零。