控制器上有什么东西?

时间:2011-09-20 05:39:51

标签: ios memory-management getter-setter pushviewcontroller

我使用Master / Detail模板和ARC在Xcode 4.3 beta下构建了一个应用程序,然后发现我无法提交它,因此将其移植到Xcode 4.2,添加了所有的内存管理。 它没有泄漏,但是每次我从主显示器访问详细记录时,分析器说正在增长 - 每次都有一个细节控制器。

我已将控制器声明为主(根)控制器中的ivar和属性(在.m文件中合成):

@interface RootViewController : UITableViewController <NSFetchedResultsControllerDelegate> {
...
    @private
    DetailViewController *detailViewController;
}
...
@property (nonatomic, retain) DetailViewController *detailViewController;
@end

...
@synthasize detailViewController;

在-tableView:didselectRowAtIndexPath调用中选择主列表项时创建新实例(添加NSLog以显示渐进式保留计数):

tableView:didselectRowAtIndexPath call (NSLog's added to show progressive retain count):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"1 dvc %i",[self.detailViewController retainCount]);
    self.detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
    NSLog(@"2 dvc %i",[self.detailViewController retainCount]);
    NSManagedObject *selectedObject = [[self fetchedResultsController] objectAtIndexPath:indexPath];
    detailViewController.detailItem = selectedObject;    
    [self.navigationController pushViewController:self.detailViewController animated:YES];
    NSLog(@"3 dvc %i",[self.detailViewController retainCount]);
    [self.detailViewController release];
    NSLog(@"4 dvc %i",[self.detailViewController retainCount]);
}

以我的思维方式,这应该正确管理对象生命周期并检查,我在RootViewController -viewWillAppear方法中放置另一个NSLog,以便每次Root(Master)视图出现时都看到保留计数。调试日志显示以下内容:

2011-09-20 15:17:34.402 ABRA[13133:207] RootViewController viewDidAppear DVC=0
2011-09-20 15:17:38.410 ABRA[13133:207] 1 dvc 0
2011-09-20 15:17:38.411 ABRA[13133:207] 2 dvc 2
2011-09-20 15:17:38.467 ABRA[13133:207] 3 dvc 9
2011-09-20 15:17:38.468 ABRA[13133:207] 4 dvc 8
2011-09-20 15:17:41.889 ABRA[13133:207] RootViewController viewDidAppear DVC=3
2011-09-20 15:17:45.137 ABRA[13133:207] 1 dvc 2
2011-09-20 15:17:45.138 ABRA[13133:207] 2 dvc 2
2011-09-20 15:17:45.330 ABRA[13133:207] 3 dvc 8
2011-09-20 15:17:45.330 ABRA[13133:207] 4 dvc 7

第一个是好的。应用程序刚刚启动,因此detailViewController保留计数为零,因为这是第一次进入tableView方法。

在alloc之后,计数是2(我以为它应该是1)!

pushViewController最多将其提升到9,然后我在方法结束时释放以放弃所有权(计数8)。

控制器“弹出”后(通过按下左侧导航栏按钮)并再次显示Root vew,计数仍为3(一个用于getter / setter,显然还有另外两个仍保留对它的引用)

因此,当通过setter创建并应用另一个新实例时,旧对象的计数仍然是2,因此即使它被新实例通过合成的setter替换它也会保留。

进一步的迭代无限回应“2,2,8,7,3”结果。仪器并不把它算作泄漏,但我确实这样做是因为足迹正在增长!

为什么-alloc / -initWithNib导致保留计数为2而不是1? 为什么推送会第一次增加保留计数7而后续增加6? 当它应该被释放时,我怎样才能找到它上面的东西?

2 个答案:

答案 0 :(得分:0)

  

为什么-alloc / -initWithNib导致保留计数为2和   不是1?为什么推送第一次增加保留计数7   然后6?我怎样才能找到它上面的东西   本应该被释放?

@property(非原子,保留)DetailViewController * detailViewController;

这应该回答你的部分答案。您的财产还保留了您的视图控制器。解决这个问题,看看你的情况是否有所改善。 (不要把它放在属性中,只需初始化一个局部变量并在方法结束时释放,NavigationController将为你保留viewController)

很难回答你问题的第二部分,因为我们不知道detailViewController上的detailItem属性会发生什么。只需修复上述内容,然后按进度编辑您的答案。

答案 1 :(得分:0)

我发现retainCount通常不可靠调试泄漏。

您是否尝试过此更改:(基本上是对dVC进行了延迟加载?)

tableView:didselectRowAtIndexPath call (NSLog's added to show progressive retain count):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"1 dvc %i",[self.detailViewController retainCount]);
    if (!self.detailViewController) {
        self.detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
        NSLog(@"2 dvc %i",[self.detailViewController retainCount]);
    }
    NSManagedObject *selectedObject = [[self fetchedResultsController] objectAtIndexPath:indexPath];
    detailViewController.detailItem = selectedObject;    
    [self.navigationController pushViewController:self.detailViewController animated:YES];
    NSLog(@"3 dvc %i",[self.detailViewController retainCount]);
  // release dVC in your dealloc
  //  [self.detailViewController release];
  //  NSLog(@"4 dvc %i",[self.detailViewController retainCount]);

}

更好的是,为什么不为您的dVC使用IBOutlet?