是什么控制了我的控制器?

发布于 2024-12-05 14:02:06 字数 2672 浏览 0 评论 0原文

我使用 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 以查看每次保留计数出现根(主)视图。调试日志显示以下内容:

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 方法的第一个条目。

分配之后,计数是 2(我原以为应该是 1)!

PushViewController 将其增加到 9,然后我在方法结束时释放以放弃所有权(计数 8)。

在控制器被“弹出”(通过按左侧导航栏按钮)并且 Root 视图再次显示后,计数仍然是 3(一个用于 getter/setter,显然还有 2 个其他仍然保留对其引用的东西)。

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

进一步的迭代无限地呼应“2,2,8,7,3”结果。 Instruments 不会将此视为泄漏,但我肯定会这样做,因为占地面积正在增加!

为什么 -alloc/-initWithNib 导致保留计数为 2 而不是 1? 为什么推送第一次将保留计数增加 7,随后增加 6? 当它应该被释放时,我如何才能找到它所持有的内容?

I'd built an app under Xcode 4.3 beta using the Master/Detail template and ARC, then found I could not submit it, so back ported it to Xcode 4.2, adding all the memory management.
It's not leaking, but the profiler says is is growing each time I visit a detail record from the master display--one detail controller each time.

I've declared the controller as an ivar and a property in the Master (root) controller (synthasized in the .m file):

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

...
@synthasize detailViewController;

New instances are created on selection of a master list item in the -tableView:didselectRowAtIndexPath call (NSLog's added to show progressive retain count):

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]);
}

To my way of thinking, this should have correctly managed the object lifecycle and to check, I put another NSLog in the RootViewController -viewWillAppear method to see that the retain count was each time the Root (Master) view appears. The debug log is showing the following:

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

The first one is good. The app has just started so the detailViewController retain count is zero, as this is the first entry into the tableView method.

After the alloc, the count is 2 (I'd have thought it should be 1)!

The pushViewController bumps this up to 9, then I release at the end of the method to relinquish ownership (count 8).

After the controller is "popped" (by pressing the Left nav bar button) and the Root vew displays again, the count is still 3 (one for the getter/setter and apparently 2 other things that still hold references to it).

So when another new instance is created and applied via the setter, the count of the old object would still be 2, so it is retained even though it is replaced by the new instance via the synthasized setter.

Further iterations echo the "2,2,8,7,3" result ad infinitum. Instruments does not count this as a leak, but I sure do because the footprint is growing!

Why is the -alloc/-initWithNib resulting in a retain count of 2 and not 1?
Why does the push increment the retain count 7 the first time and 6 subsequently?
How can I find what is holding onto it when it should have been released?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

橘寄 2024-12-12 14:02:06

为什么 -alloc/-initWithNib 导致保留计数为 2 并且
不是1?为什么第一次推送时保留计数增加 7
然后是6?当它发生时我怎样才能找到它的附着物
应该被释放吗?

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

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

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

Why is the -alloc/-initWithNib resulting in a retain count of 2 and
not 1? Why does the push increment the retain count 7 the first time
and 6 subsequently? How can I find what is holding onto it when it
should have been released?

@property (nonatomic, retain) DetailViewController *detailViewController;

This should answer part of your answer. Your property also retains your view controller. Fix this, and see if your situation improves. (Don't bother putting it in property, just init a local variable and release at the end of the method, the NavigationController will retain the viewController for you)

It is hard to answer the 2nd part of your question, simply because we don't know what happens with detailItem property on detailViewController. Just fix the above, and edit your answer with progress.

小镇女孩 2024-12-12 14:02:06

我发现,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?

I've found that retainCount is generally unreliable for debugging leaks.

Have you tried this change: (Basically do a lazy load of the 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]);

}

Better yet, why not use an IBOutlet for your dVC?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文