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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 21:40:48  来源:igfitidea点击:

how to clear an NSMutableArray of custom objects without creating memory leaks?

iphoneobjective-ciosmemory-leaksnsmutablearray

提问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

removeAllObjectswill 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 retainwhen 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 deallocmethod is never called directly. Everything is done thru the retain/releasemechanism (and the reference counting principle). So this is the releasemethod that gets called, not the deallocdirectly. The deallocmethod is only called by the runtime if the last releasecall 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) 为零,则该方法仅由运行时调用,这意味着该对象确实已从内存中释放,因为没有人再使用它。

NSArrayand all container classes in Cocoa (NSDictionary, NSSet, ...) do retain their values. So when you add an objet to a container like NSArray, it will retainthat value. And when you remove that value (including when you call removeAllObjects") it will releaseit.

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 releaseor autoreleaseif you called alloc, retainor copymethods. That's always the responsability of the objet which did the alloc/retain/copyto call the release/autorelease. Never leave a alloc/retain/copywithout a pending release/autoreleasecall to balance it (or you will have leaks), but on the other hand never call release/autoreleaseif you didn't do the alloc/retain/copycall yourself.

Memory Mgmt 规则很容易遵循:但唯一重要的规则是您只需调用releaseautorelease如果您调用alloc,retaincopy方法。这始终是执行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 removeAllObjectsmethod sends releasemessage to all the objects. The releasemethod decrements the objects reference count. And if the reference count of an object reaches 0then the deallocmessage will be sent to the object.

基本上removeAllObjects方法向release所有对象发送消息。该释放方法递减对象引用计数。如果对象的引用计数达到,0dealloc消息将发送到该对象。

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 释放其所有对象以及该数组。