我使用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? 当它应该被释放时,我怎样才能找到它上面的东西?
答案 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?