2010-07-11 89 views
1

我创建了UITableView的子类,并希望将它与UITableViewController一起使用,以在出现键盘时获得自动滚动的好处。在对的loadView我的视图控制器(来自衍生的UITableViewController)我做了以下内容:不会重新分配UITableViewController的tableView属性导致泄漏?

- (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... 
} 

...各种讨厌的崩溃发生。任何人都可以向我解释简单的重新分配是否会导致泄漏,如果是的话,如何正确地做到这一点?

在此先感谢。

回答

1

不,它不会导致泄漏,因为setter方法setTableView:(当您为属性指定新值时会调用该方法)将自动释放旧值。这是属性的用途。

+0

有点晚了,但我很困惑。有双重保留,因此上面的例子会有泄漏,不是吗? – Kalle 2010-07-25 13:14:12

+0

你是对的,卡勒,在OP的代码中有泄漏。我没有看到任务,只回答了OP的问题,“这不应该导致任何self.tableView在重新分配之前引用的泄漏?”。接得好。 – 2010-07-25 13:55:24

0

正如Ole Begemann所说,当您使用点符号进行赋值时,会发生比纯粹赋值更多的事情。由于setTableView:是“保留产权”,它看起来是这样的:

- (void)setTableView:(UITableView *)newTable 
{ 
    if(newTable != tableView) { 
    [tableView release]; 
    tableView = [newTable retain]; 
    } 
} 

所以在你的“好”方法的问题如下。 如果您只是在桌面视图对象上调用release,那么您没有使用属性设置器,这意味着您没有将tableView设置为nil。当你调用self.tableView = [[MyCustomTableView alloc] init...时,当前的tableView指向一个非零的,已经释放的内存块。这块内存是setTableView:将尝试再次释放的内存块,引发EXC_BAD_INSTRUCTION。

当您在某个对象上调用release时,指针可能在将来被重用,因此以后始终将其设置为nil。通过这种方式,您可以将指针标记为释放,并且您不会冒险过度分级。或者只是使用保留属性,当您将其分配给nil时,将为您执行release

0

其实你的例子会导致泄漏。

self.tableView = [[MyCustomTableView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame style:UITableViewStyleGrouped]; 

设置self.tableView将增加1保留,而ALLOC将增加1

保留您稍后集self.tableView到另一个值,保留计数减1,留下1,因此你分配的MyCustomTableView永远不会被释放。

你的loadView崩溃的原因是因为初始表视图在你分配和添加你自己之前已经存在,正确设置,并且保留1。所以当你释放它的时候,系统也会尝试释放它,但是到那时它已经被释放,并且随之而来的是糟糕。

正确的方法做到这一点是(自动)释放分配MyCustomTableView

self.tableView = [[[MyCustomTableView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame style:UITableViewStyleGrouped] autorelease]; 

这样一来,将有1只保留计数,这将下降到零,当你(重新)设置self.tableView

相关问题