在添加到视图后,我正在检查子视图的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,因为工具栏在初始化并添加到自身视图后,保留计数将变为2。
2 .在工具栏removeFromSuperView之后,retainCount将变为1。
工具栏调用release方法后,retainCount仍然是1,不能变为0。在我的选项中,由于超级视图仍然是工具栏(自身视图不是释放),所以工具栏不能重新使用为0。
4、如果调用设置为nil的工具栏,则retainCount为0。这个日志是无用的。
我的问题是:
A)工具条调用removeFromSuperView和release接口,结果是一样的,工具条retainCount只会变成1,所以如果我只用它们来测试代码,结果是一样的。那么,我是否可以得出结论,用户只能调用每个API都是OK的?
B)从苹果文档中,子视图被添加到自身视图中,自身视图仍然是工具栏句柄,所以在dealloc方法中,如果不调用viewDidUnload,工具栏retainCount不能减少到0。如果内存不足,系统会减少无用的视图,并调用viewDidUnload方法,它会自动将工具栏的retainCount减少到0。所以在dealloc方法中,我是否应该将工具栏设置为nil。如果我将工具栏设置为空,我会感到困惑,当调用viewDidUnload方法时,工具栏是否会缩小?有没有内存泄露?
谢谢。
发布于 2012-06-14 15:57:07
首先,如果你的代码反映了你的真实代码,那么你的dealloc方法就有一个大问题:
- (void) dealloc{
[toolbar removeFromSuperView];
[toolbar release]
toolbar = nil;
}您不能调用[super dealloc]。如果不调用super,self.view将永远不会被释放(并最终被释放)。
这应该会修复您的内存泄漏(至少部分修复):
- (void) dealloc{
[toolbar release];
[super dealloc];
}您可以注意到,我删除了对removeFromSuperView的调用,因为这是在self.view实际释放时自动为您完成的,因此您不需要自己执行此操作。在任何情况下,调用removeFromSuperView也不会导致任何问题。
关于您的问题,我假设您的toolbar属性被声明为retain (根据您提交的代码,这是我最敏感的假设)。
如果toolbar是属性的retain子级,那么为其分配新创建的视图的正确方法是:
toolbar = [[[UIToolbar alloc] initWithFrame:nil] autorelease];请注意autorelease;如果没有它,您的保留/释放呼叫将受到影响。这就解释了为什么您需要先调用release,然后在dealloc中nil属性:
- (void)dealloc {
...
[toolbar release]
toolbar = nil;
....
}通过这样做,您将释放toolbar两次;但是,由于您在分配给retain属性时没有使用autorelease,因此这将产生正确的结果。
a)工具条调用removeFromSuperView和release接口,结果是一样的,工具条retainCount只会变成1,所以如果我只用它们来测试代码,结果是一样的。那么,我是否可以得出结论,用户只能调用每个API都是OK的?
正如我所说的,您不需要直接调用removeFromSuperView来获取在dealloc时发布的子视图,因为self.view将为您做这件事。如果您想要删除一个子视图,同时保留superview (假设您显示了一个标签,然后将其删除),那就是另一回事了;在这种情况下,您需要同时调用这两种方法,否则就会发生泄漏。
b)从苹果文档中,子视图被添加到自身视图中,自身视图保留了工具栏句柄,因此在dealloc方法中,如果不调用viewDidUnload,则工具栏retainCount不能被减少到0。如果内存不足,系统会减少无用的视图,并调用viewDidUnload方法,它会自动将工具栏的retainCount减少到0。所以在dealloc方法中,我是否应该将工具栏设置为nil。如果我将工具栏设置为空,我会感到困惑,当调用viewDidUnload方法时,工具栏是否会缩小?有没有内存泄露?
如果我正确理解了您的疑问,关键是如果您将toolbar属性发送给viewDidUnload中的nil,那么当调用此方法时(无论是显式删除视图还是发出内存警告),您的子视图都将被正确处理;如果此后调用控制器的dealloc,则您的属性已经有了一个nil值,因此释放它不会有任何效果(但这很好,因为它已经在viewDidUnload中释放了)。
另一方面,如果您没有在viewDidUnload中释放您的属性,那么发生的情况是,如果视图在内存警告后再次显示,那么loadView/viewDidLoad将被再次调用;但是在这种情况下,当您创建工具栏子视图并将其引用分配给toolbar属性时(假设它是retain类型),那么较旧的对象将自动为您释放,因此您不会有任何内存泄漏;发生的情况是您使用的内存比您可以使用的内存多了一点(因为工具栏直到再次创建self.view时才被释放)。
https://stackoverflow.com/questions/11028512
复制相似问题