0

我最近开始使用 cocoa 和 Objective-C,虽然我对软件概念并不陌生,而且我在 NSMutableArray 类中遇到了一些奇怪且出乎意料的行为。

首先,我创建并填充了一个“NSMutableArray”对象,其中我的自定义对象“CustomClass”类工作正常。然后我继续尝试删除其中一个对象,但我没有得到我想要的结果。

// NSMutableArray *Array is already initialized and loaded with 5 CustomClass Objects
//   stored in variables 'CustomClassObject1' through 'CustomClassObject5'. 
[Array removeObject:CustomClassObject4];

这段代码并没有像我想要的那样简单地删除第四个条目,而是将第四个条目设置为“nil”(即 (id) 0x00000000),并且更令人困惑的是,删除了数组中的最后一个条目

在我的理解中,这不应该发生——应该发生的只是第四个条目应该被删除,由第五个条目代替。相反,我现在有一个包含三个对象和一个 nil 的数组!

我也试过

int position = [Array indexOfObject:CustomClassObject4];
[Array removeObjectatIndex:position];

只为得到同样的结果。有谁知道为什么会这样?我是不是误会了什么?

谢谢!

代码:

NSMutableArray *Array = [NSMutableArray array];

CustomClass *CustomClassObject1 = [[CustomClass alloc] init];
CustomClass *CustomClassObject2 = [[CustomClass alloc] init];
CustomClass *CustomClassObject3 = [[CustomClass alloc] init];
CustomClass *CustomClassObject4 = [[CustomClass alloc] init];
CustomClass *CustomClassObject5 = [[CustomClass alloc] init];

[Array AddObject:CustomClassObject1];
[Array AddObject:CustomClassObject2];
[Array AddObject:CustomClassObject3];
[Array AddObject:CustomClassObject4];
[Array AddObject:CustomClassObject5];

此时输出:

_Array = (NSMutableArray *) 0x0885c2c0 @ "5 Objects"
[0] = (CustomClass *) 0x0885c5f0
[1] = (CustomClass *) 0x0885c630
[2] = (CustomClass *) 0x0885c690
[3] = (CustomClass *) 0x0885c6f0
[4] = (CustomClass *) 0x0885c730

然后:

[Array removeObject:CustomClassObject4];

此时输出:

_Array = (NSMutableArray *) 0x0885c2c0 @ "4 Objects"
[0] = (CustomClass *) 0x0885c5f0
[1] = (CustomClass *) 0x0885c630
[2] = (CustomClass *) 0x0885c690
[3] = (id) 0x00000000

相反,如果我删除第三个对象,

[Array removeObject:CustomClassObject3];

输出是:

_Array = (NSMutableArray *) 0x0885c2c0 @ "4 Objects"
[0] = (CustomClass *) 0x0885c5f0
[1] = (CustomClass *) 0x0885c630
[2] = (id) 0x00000000
[3] = (CustomClass *) 0x0885c6f0
4

2 回答 2

2

这一切都归结为 ARC 如何处理局部变量。有一会儿,我将假装关闭 ARC,以向您展示您的代码是如何进行内存管理的,以进行说明:

NSMutableArray *Array = [NSMutableArray array];

//All of these are initialized with a +1 retain count
CustomClass *CustomClassObject1 = [[CustomClass alloc] init];
CustomClass *CustomClassObject2 = [[CustomClass alloc] init];
CustomClass *CustomClassObject3 = [[CustomClass alloc] init];
CustomClass *CustomClassObject4 = [[CustomClass alloc] init];
CustomClass *CustomClassObject5 = [[CustomClass alloc] init];

//The array retains what gets put into it, meaning it owns these variables
//And gives them a total reference count of +2
[Array AddObject:[CustomClassObject1 retain]];
[Array AddObject:[CustomClassObject2 retain]];
[Array AddObject:[CustomClassObject3 retain]];
[Array AddObject:[CustomClassObject4 retain]];
[Array AddObject:[CustomClassObject5 retain]];

//The compiler inserts a release for each of those objects because you
//Don't reference them before the method's scope ends.  The array still owns
//them, so they all have a total reference count of +1 at this point.
[CustomClassObject1 release];
[CustomClassObject2 release];
[CustomClassObject3 release];
[CustomClassObject4 release];
[CustomClassObject5 release];

当你删除一个对象时,数组会减少它的引用计数,所以当你删除时CustomClassObject4,它的引用计数会下降到一个很大的 0,并且它会被释放。这就是你看到的 nil 。要修复它,请将这些对象保留在该方法范围之外的强 iVar、属性或全局中。

于 2013-06-15T05:55:56.103 回答
0

你能不能尝试一些更简单的东西:

NSMutableArray *array = [NSMutableArray new];
[array addObject: [[CustomClass alloc] init] ];
// repeat for as many times you want.

// Fast enumerate the loop and get an output - You class will need to provide method id
for ( CustomClass * c in array ) NSLog( @"Class id: %@", [c id] );

// Then try to delete any random object.
[array removeObjectAtIndex: [array indexOfObject: object] ];

// And repeat the enumeration
for ( CustomClass * c in array ) NSLog( @"Class id: %@", [c id] );

你能试试这个并告诉我们发生了什么吗?此外,在每个添加和删除操作中添加断点。

确保您启用了弧,并且您的代码在自动释放池中!

于 2013-06-15T05:52:11.420 回答