0

私は(を使用して)継続的に反復するものNSMutableArrayを持っています。これは、画面を連続的に移動するために行います。UIImageViewsCADisplayLinkUIImageViews

配列からを削除するとUIImageView、次のエラーが発生することがあります。

EXC_BAD_ACCESS (code=1, address=0x20000008)

ただし、ARC / iOS6を使い始める前は、以前は「配列が列挙中に変異しました」というエラーが発生していたので、この2つのエラーはまったく同じ意味だと思いますが、よくわかりません。

とにかくここに私の質問があります。次のいずれかの方法を使用して配列からaを削除するUIImageViewと、上記のエラーが発生します。

[imageViews removeObject:imageView];

[imageViews performSelector:@selector(removeObject:) withObject:imageView];

[imageViews performSelectorOnMainThread:@selector(removeObject:) withObject:imageView waitUntilDone:YES];

ただし、以下の方法のいずれかを使用しても、エラーが発生することはありません。

[imageViews performSelectorOnMainThread:@selector(removeObject:) withObject:imageView waitUntilDone:NO];

[imageViews performSelector:@selector(removeObject:) withObject:imageView afterDelay:.01];

それで、誰かが私に、NSMutableArray上記の最初のメソッドのセットを使用してオブジェクトを削除すると、「列挙中に配列が変異した」エラーであると私が信じているのに、2番目のメソッドのセットを使用してもそのエラーが発生しない理由を説明できますか?

私はこのエラーを回避するために上記の2番目のメソッドセットを常に使用しています(そしてそれらを使用するとすべてが完全に機能します)が、それらを使用したときに問題が解決する理由と安全かどうかを正確に知りたいですこれらの2つの方法のいずれかを使用します。

質問を投稿するのはこれが初めてなので、間違った方法で投稿する場合はご容赦ください。

4

2 に答える 2

2

CADisplayLinkはバックグラウンドスレッドをコールバックするため、問題の配列をスケジュールして特定のオブジェクトをそのスレッドから削除することにより、別のオブジェクトが配列を変更または列挙している最中であり、例外がスローされる可能性があります。上位2つのメソッドは、配列への同期アクセス(NSMutableArrayが提供しない)を必要とし、メインスレッドではなく現在のスレッドの実行ループでスケジュールされるため、機能しません。したがって、それぞれの実行は保証されません。同じリソースに同時にアクセスしないようにします。下の2つは、メインスレッドで配列を変更していると仮定すると、その実行ループで、列挙する命令と同時に変更する命令をスケジュールすることができないためです(1つのスレッドで2つのコードを実行することはできません)同時、特に、そのコードが実行ループの次の反復でスケジュールされている場合)、配列へのアクセスがはるかに安全になります。遅延を使用することにより、これまで機能してきた競合状態を作成しますが、後日、競合状態に戻る可能性があります。

于 2013-03-11T22:35:27.190 に答える
1

配列を列挙する場合(for…in…ループでステップスルーするか、NSEnumeratorを使用する)、列挙では、ループ自体または別のスレッドで同時に配列を変更しない必要があります(したがって、元の警告)。

下の2つのメソッドが機能する理由はわかりません。内部的には、列挙に影響を与えない方法で配列を変更していると思います。

そうは言っても、それは悪い習慣であり、列挙中に配列を変更することは、いかなる方法でもお勧めしません。今日は機能しても、明日は機能しない可能性があります。私がお勧めするのは、列挙が完了するまで削除するインデックスを保存してから、この回答のように削除することです。

于 2013-03-11T22:02:25.663 に答える