首页 文章

如何在不创建内存泄漏的情况下清除自定义对象的NSMutableArray?

提问于
浏览
15

如果我有自定义对象的NSMutableArray,我怎样才能轻松清除数组而不会导致任何内存问题?假设自定义对象类中有一个dealloc方法,它正确地释放了一个实例变量等 .

例如,可以使用NSArray“removeAllObjects”方法吗?

  • 如果是 - 这是如何工作的 - “removeAllObjects”会在每个对象上调用“dealloc”方法,因为它会删除它们

  • 如果不是 - 最简单的方法是什么?

EDIT (after 4 replies) - 在回复之后澄清的最后一个问题 - 我仍然不太确定我设置保留的自定义对象中的实例变量/属性?这些似乎只通过我的自定义对象类中的"dealloc"方法发布,我们手动与[超级发布]一起执行此操作 .

因此,如果重新清除数组,如果我执行removeAllObjects,然后NSArray向我的自定义对象发出“释放”,但不调用“dealloc”,那么我的实例变量如何被释放?

4 回答

  • 3

    removeAllObjects 将从数组中删除该对象 . 此过程将向对象发送释放消息,这将减少其引用计数 . 当引用计数达到零时,将取消分配对象 .

    不要这样做,因为它会泄漏 .

    NSObject *object = [[NSObject alloc] init];       + 1
    [array addObject:object];                         + 1
    [array removeAllObjects];                         - 1
                                                    =======
                                                    = + 1 -> Leak
    

    这是正确的方法:

    NSObject *object = [[[NSObject alloc] init] autorelease]; + 1 (from alloc) - 1 (from autorelease)
    [array addObject:object];                         + 1
    [array removeAllObjects];                         - 1
                                                    =======
                                                    =   0 -> Object will be deallocated
    

    您可以只释放数组,而不是调用removeAllObjects . 如果一个数组被释放,那么它内部的所有内容都会被释放,如果没有对该对象的其他引用,它将被解除分配 .

  • 32

    是的,只需拨打 removeAllObjects 即可 . 只是为了确保,当您向数组添加对象或创建包含对象的数组时,不要调用 retain . 这是自动完成的 .

    关于 dealloc ,再次将自动完成,您无法预测何时 .

    你需要在dealloc中唯一拥有的是数组对象本身 . 也就是说,假设它是一个实例变量或ivar?

    要检查一切是否正常,请使用Product - > Analyze运行Analyzer . 然后使用Leaks仪器在应用程序中为应用程序提供配置文件,以检查您的代码是否都没有导致任何内存泄漏 .

  • 1

    基本上 removeAllObjects 方法向所有对象发送 release 消息 . 发布方法 decrements the objects reference count . 如果对象的引用计数达到 0 ,那么 dealloc 消息将被发送到该对象 .

    您的问题的答案是调用 [array removeAllObjects] 是完全安全的 . 顺便说一句,如果你不再需要数组,你可以直接调用 [array release] ,它释放所有对象以及数组 .

  • 1

    永远不会直接调用 dealloc 方法 . 一切都通过 retain / release 机制(以及引用计数原理)完成 . 所以这是被调用的 release 方法,而不是 dealloc . 如果最后 release 调用导致对象的引用计数(retainCount)达到零,则运行时仅调用 dealloc 方法,这意味着该对象确实已从内存中释放,因为没有人再使用它 .

    NSArray 和Cocoa中的所有容器类( NSDictionaryNSSet ,...)都保留了它们的值 . 因此,当您将objet添加到像 NSArray 这样的容器时,它将 retain 该值 . 当你删除该值(包括当你调用removeAllObjects时),它将 release 它 .

    内存管理规则很容易遵循:但唯一重要的规则是,如果调用 allocretaincopy 方法,则只需调用 releaseautorelease . 这始终是objet的责任,它使 alloc / retain / copy 调用 release / autorelease . 永远不要留下 alloc / retain / copy 没有待处理的 release / autorelease 来 balancer 它(或者你会有泄漏),但另一方面如果你没有自己调用 alloc / retain / copy ,则永远不要调用 release / autorelease .

    好榜样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.
    

    好榜样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
    

    好例子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
    

    不好的例子:

    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!
    

相关问题