0

私は最近、ココアと Objective-C を使い始めましたが、ソフトウェアの概念については初めてではありません。NSMutableArray クラスで、好奇心旺盛で予期しない動作に遭遇しました。

まず、正常に動作するクラス「CustomClass」のカスタム オブジェクトを使用して、「NSMutableArray」オブジェクトを作成して入力します。次に、オブジェクトの 1 つを削除しようとしましたが、必要な結果が得られません。

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

このコードは単純に 4 番目のエントリを削除するのではなく、4 番目のエントリを「nil」((id) 0x00000000) に設定し、さらに紛らわしいことに、配列の最後のエントリを削除します。

私の理解では、これは発生するはずがありません。発生する必要があるのは、4 番目のエントリを削除し、5 番目のエントリに置き換えることだけです。代わりに、3 つのオブジェクトと 1 つの 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

代わりに 3 番目のオブジェクトを削除すると、

[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] );

これを試して、何が起こったのか教えてください。また、追加および削除操作ごとにブレークポイントを追加します。

arc が有効になっていること、およびコードが autorelease プール内にあることを確認してください!

于 2013-06-15T05:52:11.420 に答える