添加到视图后,我检查子视图的retainCount。代码是:
- (void) loadView{
//...
toolbar = [[UIToolbar alloc] initWithFrame:nil];
[[self view] addSubView:toolbar];
}
- (void) dealloc{
NSLog(@"count=%d", [toolbar retainCount]); // count=2
[toolbar removeFromSuperView];
NSLog(@"count=%d", [toolbar retainCount]); // count=1
[toolbar release]
NSLog(@"count=%d", [toolbar retainCount]); // count=1
toolbar = nil;
NSLog(@"count=%d", [toolbar retainCount]); // count=0
}
从dealloc {}的代码中,我有一些问题:
1,工具栏的第一个日志retainCount是2,因为工具栏在init之后并添加到自我视图中,retaincount将变为2。
2,在工具栏removeFromSuperView之后,retainCount将变为1。
3,工具栏调用release方法后,retainCount仍为1,它不能变为0.在我的选项中,因为超级视图仍然是工具栏(自我视图不释放),所以工具栏可以不会减少到0。4,如果调用工具栏设置为nil,则retainCount将为0.此日志无用。
我的问题是:
a)工具栏调用removeFromSuperView和release API,结果是一样的,工具栏retainCount只会变为1.所以如果我测试代码只使用它们中的每一个,结果是一样的。那么,我可以断定用户只能调用每一个API吗? b)从apple文档中,子视图被添加到自我视图中,自我视图仍然是工具栏句柄,因此在dealloc方法中,如果未调用viewDidUnload,则工具栏retainCount不能减少为0如果内存不足,系统会减少无用的视图并调用viewDidUnload方法,它会自动将工具栏的retainCount减少为0.所以在dealloc方法中,我应该将工具栏设置为nil。如果我将工具栏设置为nil,我很困惑,当调用viewDidUnload方法时,工具栏会减少与否?有没有妈妈泄密?THX。
答案 0 :(得分:2)
首先,如果您的代码反映了您的真实代码,那么您的dealloc
方法存在很大问题:
- (void) dealloc{
[toolbar removeFromSuperView];
[toolbar release]
toolbar = nil;
}
你没有打电话给[super dealloc]
。如果不调用[super dealloc],self.view
将永远不会被释放(并最终被释放)。
这应该可以解决你的内存泄漏问题(部分,至少):
- (void) dealloc{
[toolbar release];
[super dealloc];
}
你可以注意到我已经删除了对removeFromSuperView
的调用,因为当self.view
实际被释放时,这是自动完成的,因此您不需要自己执行此操作。无论如何,调用removeFromSuperView
也不会造成任何问题。
关于您的问题,我假设您的toolbar
属性被声明为retain
(根据您提交的代码,这是我最感觉到的假设)。
如果toolbar
是retain
属性的孩子,那么为其分配新创建的视图的正确方法是:
toolbar = [[[UIToolbar alloc] initWithFrame:nil] autorelease];
请注意autorelease
;如果不存在,您的保留/释放呼叫会受损。这可以解释您是否需要首先在dealloc中调用release
然后nil
属性:
- (void)dealloc {
...
[toolbar release]
toolbar = nil;
....
}
通过这样做,你发布toolbar
两次;但由于在分配retain属性时没有使用autorelease
,这将产生正确的结果。
a)工具栏调用removeFromSuperView和release API,结果是一样的,工具栏retainCount只会变为1.所以如果我测试代码只使用它们中的每一个,结果是一样的。那么,我可以断定用户只能调用每一个API吗?
正如我所说,您无需直接致电removeFromSuperView
即可在dealloc
时发布子视图,因为self.view
会为您执行此操作。当您想要在保持superview
的同时删除子视图时,这是另一回事(假设您显示标签然后将其删除);在这种情况下,你需要同时调用它们,否则你会有泄漏。
b)从apple文档中,子视图被添加到自我视图中,自我视图仍然是工具栏句柄,因此在dealloc方法中,如果未调用viewDidUnload,则工具栏retainCount不能减少为0如果内存不足,系统会减少无用的视图并调用viewDidUnload方法,它会自动将工具栏的retainCount减少为0.所以在dealloc方法中,我应该将工具栏设置为nil。如果我将工具栏设置为nil,我很困惑,当调用viewDidUnload方法时,工具栏会减少与否?有没有妈妈泄密?
如果我理解你的疑问,重点是如果你在toolbar
中将nil
属性发送到viewDidUnload
,那么当调用此方法时(或者当你明确删除查看或发出内存警告时)您的子视图被正确处理;如果今后为您的控制器调用dealloc
,则您的属性已经有nil
值,因此释放它不会产生任何影响(但这很好,因为它已在viewDidUnload
中发布)。
另一方面,如果你没有在viewDidUnload
中发布你的属性,那么如果在内存警告后再次显示视图,那么会发生loadView
/ viewDidLoad
再次被召唤;但在这种情况下,当您创建工具栏子视图并将其引用分配给toolbar
属性(假设它是retain
种类)时,则会自动为您释放旧对象,因此您不需要有任何内存泄漏;会发生什么事情是你使用了更多的内存(因为在再次创建self.view
之前工具栏没有被释放)。