ios 如何清除自定义对象的 NSMutableArray 而不造成内存泄漏?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7596648/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
how to clear an NSMutableArray of custom objects without creating memory leaks?
提问by Greg
If I have an NSMutableArray of custom objects, how can I must easily clear the array without causing any memory issues? Assume that the custom object class has a dealloc method in it which correctly released an instance variables etc.
如果我有一个 NSMutableArray 的自定义对象,我怎样才能轻松地清除数组而不引起任何内存问题?假设自定义对象类中有一个 dealloc 方法,它正确地释放了一个实例变量等。
For example is it ok to use the NSArray "removeAllObjects" method?
例如可以使用 NSArray“removeAllObjects”方法吗?
If yes - how does this work - does "removeAllObjects" call the "dealloc" method on each object as it removes them
If no - what would be the easiest approach to use?
如果是 - 这是如何工作的 - “removeAllObjects”是否在删除每个对象时调用每个对象的“dealloc”方法
如果没有 - 最简单的使用方法是什么?
EDIT (after 4 replies)- One last question of clarification after the great replies - I'm still not quite sure about the instance variables/properties in my custom object that I have set to retain? These seem to be only released via the the "dealloc" method in my custom object class, where we do this manually along with [super release].
编辑(在 4 次回复后)- 在得到很好的回复后澄清的最后一个问题 - 我仍然不太确定我设置为保留的自定义对象中的实例变量/属性?这些似乎只能通过我的自定义对象类中的“dealloc”方法释放,我们在其中手动与 [super release] 一起执行此操作。
So if, re clearing an array, if I do a removeAllObjects, and then NSArray issues a "release" to my custom objects, but doesn't call "dealloc", then how do my instance variables get released?
因此,如果重新清除数组,如果我执行 removeAllObjects,然后 NSArray 向我的自定义对象发出“释放”,但不调用“dealloc”,那么我的实例变量如何释放?
回答by Matthias Bauch
removeAllObjects
will remove the object from the array. This process will send a release message to the object and this will decrease its reference count. When the reference count reaches zero the object will be deallocated.
removeAllObjects
将从数组中删除对象。此过程将向对象发送释放消息,这将减少其引用计数。当引用计数达到零时,对象将被释放。
don't do it like this, because it will leak.
不要这样做,因为它会泄漏。
NSObject *object = [[NSObject alloc] init]; + 1
[array addObject:object]; + 1
[array removeAllObjects]; - 1
=======
= + 1 -> Leak
this is the correct way:
这是正确的方法:
NSObject *object = [[[NSObject alloc] init] autorelease]; + 1 (from alloc) - 1 (from autorelease)
[array addObject:object]; + 1
[array removeAllObjects]; - 1
=======
= 0 -> Object will be deallocated
Instead of calling removeAllObjects you could just release the array. If an array is deallocated everything that's inside of it gets released and if there is no other reference to the object it will be deallocated.
您可以只释放数组,而不是调用 removeAllObjects。如果一个数组被释放,它里面的所有东西都会被释放,如果没有对该对象的其他引用,它将被释放。
回答by Max MacLeod
Yep, just call removeAllObjects
. Just to be sure, you don't call retain
when you add an object to an array or when you create an array with objects. That's done for you automatically.
是的,只需调用removeAllObjects
。可以肯定的是,retain
当您将对象添加到数组或使用对象创建数组时,您不会调用。这是自动为您完成的。
Regarding dealloc
, again that will be done automatically, and you can't predict when.
关于dealloc
,这将再次自动完成,您无法预测何时。
The only thing you need to have in the dealloc is the array object itself. That is, assuming it's an instance variable or ivar?
在 dealloc 中唯一需要的是数组对象本身。也就是说,假设它是一个实例变量或 ivar?
To check everything is good, run the Analyzer using Product -> Analyze. And then give the app a profile in Instruments using the Leaks instrument to check that none of your code is causing any memory leaks.
要检查一切是否正常,请使用 Product -> Analyze 运行 Analyzer。然后使用 Leaks 工具在 Instruments 中为应用程序提供一个配置文件,以检查您的代码是否导致任何内存泄漏。
回答by AliSoftware
The dealloc
method is never called directly. Everything is done thru the retain
/release
mechanism (and the reference counting principle). So this is the release
method that gets called, not the dealloc
directly. The dealloc
method is only called by the runtime if the last release
call causes the reference counting (retainCount) of the object reaches zero, meaning that the object really is deallocated from memory as noone uses it anymore.
该dealloc
方法从不直接调用。一切都是通过retain
/release
机制(和引用计数原则)完成的。所以这是release
被调用的方法,而不是dealloc
直接调用的方法。dealloc
如果最后一次release
调用导致对象的引用计数 (retainCount) 为零,则该方法仅由运行时调用,这意味着该对象确实已从内存中释放,因为没有人再使用它。
NSArray
and all container classes in Cocoa (NSDictionary
, NSSet
, ...) do retain their values. So when you add an objet to a container like NSArray
, it will retain
that value. And when you remove that value (including when you call removeAllObjects") it will release
it.
NSArray
并且 Cocoa ( NSDictionary
, NSSet
, ...) 中的所有容器类都保留它们的值。因此,当您将 objet 添加到诸如 之类的容器时NSArray
,它将具有retain
该值。当您删除该值时(包括当您调用 removeAllObjects" 时),它就会删除release
它。
Memory Mgmt rules are easy to follow: but the only rule that matters it that you only have to call release
or autorelease
if you called alloc
, retain
or copy
methods. That's always the responsability of the objet which did the alloc
/retain
/copy
to call the release
/autorelease
. Never leave a alloc
/retain
/copy
without a pending release
/autorelease
call to balance it (or you will have leaks), but on the other hand never call release
/autorelease
if you didn't do the alloc
/retain
/copy
call yourself.
Memory Mgmt 规则很容易遵循:但唯一重要的规则是您只需调用release
或autorelease
如果您调用alloc
,retain
或copy
方法。这始终是执行alloc
/ retain
/copy
调用release
/的对象的责任autorelease
。切勿用alloc
/ retain
/copy
没有挂起release
/autorelease
调用平衡它(或者你将有泄漏),但另一方面不调用release
/autorelease
如果你没有做alloc
/ retain
/copy
调用自己。
Good example 1:
好例子1:
MyClass* obj = [[MyClass alloc] init]; // here you do an alloc
[myArray addObject:obj]; // the NSArray "myArray" retains the object obj
// so now you can release it, the array has the responsability of the object while it is held in the array
[obj release]; // this release balance the "alloc" on the first line, so that's good
[myArray removeAllObjects]; // there the object held by the array receive a release while being removed from the array. As nobody retains it anymore, its dealloc method will be called automatically.
Good example 2:
好例子2:
MyClass* obj = [[MyClass alloc] init]; // here you do an alloc
[myArray addObject:obj]; // the NSArray "myArray" retains the object obj
// so now you can release it, the array has the responsability of the object while it is held in the array
[myArray removeAllObjects]; // there the object held by the array receive a release while being removed from the array. But your own code still retains a reference to it (because of the "alloc" on first line) so it won't be removed from memory right now
[obj release]; // this release balance the "alloc" on the first line, and as nobody retains the object anymore, its dealloc method will be called and it will be deallocated from memory
Good example 3:
好例子3:
MyClass* obj = [self getSomeObjectFromAnotherMethod]; // here you don't have an "alloc" on this line
[myArray addObject:obj]; // the array retains the object
[myArray removeAllObjects]; // the array release the object while it removes it from the array
// no need to call "release" here as there is no "alloc" done in the scope of this code
Bad example:
不好的例子:
MyClass* obj = [self getSomeObjectFromAnotherMethod]; // here you don't have an "alloc" on this line
[myArray addObject:obj]; // the array retains the object
[myArray removeAllObjects]; // the array release the object while it removes it from the array
[obj release]; // Crash here! obj does not exists anymore and has been deallocated from memory before this line!
回答by EmptyStack
Basically removeAllObjects
method sends release
message to all the objects. The releasemethod decrements the objects reference count. And if the reference count of an object reaches 0
then the dealloc
message will be sent to the object.
基本上removeAllObjects
方法向release
所有对象发送消息。该释放方法递减对象引用计数。如果对象的引用计数达到,0
则dealloc
消息将发送到该对象。
The answer to your question is calling [array removeAllObjects]
is completely safe. By the way if you don't want the array anymore you can directly call [array release]
which releases all its objects as well as the array.
你的问题的答案是调用[array removeAllObjects]
是完全安全的。顺便说一句,如果您不再需要该数组,您可以直接调用[array release]
which 释放其所有对象以及该数组。