3

これは本当に奇妙です...

アプリを実行すると、アプリが開いていてビューが構築されている間に、次のようになります。

Collection <CALayerArray: 0x124650> was mutated while being enumerated.

コードトレースは次のようになります。

main
UIApplicationMain
-[UIApplication _run]
CFRunLoopRunInMode
CFRunLoopRunSpecific
_UIApplicationHandleEvent
-[UIApplication sendEvent:]
-[UIApplication handleEvent:withNewEvent:]
-[UIApplication _runWithURL:sourceBundleID:]
-[UIApplication _performInitilizationWithURL:sourceBundleID:]
-[AppDelegate applicationDidFinishLaunching:]
+[Controller initializeController] //This is my own function
    [window addSubview: pauseMenuController.view] //This is the last point of my code it goes through
-[UIView(Hierarchy) addSubview:]
-[UIView(Internal) _addSubview:positioned:relativeTo:]
-[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:]
-[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:]
-[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:]
_NSFastEnumerationMutationHandler
objc_exception_throw

私はゲームを何度も何度も実行しましたが、これを見たことがありませんでしたが、突然ポップアップしました。奇妙なことに、このコードがすべて呼び出されるまで、他のスレッド(私が知っている)を作成していません。UIViewでアクセスしているときに変更される可能性のあるものについて誰かが説明してくれれば、これをデバッグするのが簡単になります。すでに何かを追加しているときに、ビューに何かを追加することと関係がありますか?何か案は?

4

5 に答える 5

17

ビューにデリゲートを割り当てたサブレイヤーがビューにある可能性はありますか? これにより、通常、 を呼び出すときにビューが無限に再帰します (つまり、スタック制限に達するまで) _makeSubtreePerformSelector:withObject:withObject:copySublayers:

これは、CALayer のデリゲートが UIView である場合、その CALayer が UIView に属し、UIView が階層の一部であると UIView が想定しているためです。ただし、独自の CALayer を作成し、デリゲートを UIView に割り当てると、UIView は再帰の一部として自分自身を呼び出すことになります。

于 2009-11-10T22:50:01.230 に答える
4

これは並行性の例外ではありません。列挙突然変異の例外は、何か (おそらく同じスレッドのループ内) が、ループが反復している配列/セット/辞書を変更したときに発生します。

addSubview: はスタック上にあるため、何かが構築中に UIView のサブビューの 1 つを削除しようとしていると推測されます。

実行される可能性のあるメソッドをオーバーライドしていますか? addSubview や場合によっては layoutSubviews のようなものですか? これらのいずれかがサブビューを削除している場合、これが問題の原因になります。

于 2009-11-11T07:34:30.850 に答える
0

同じバグに遭遇しました。非メインスレッドでビュー階層を変更していました。ビューに対するすべての変更がメイン スレッドで実行されていることを確認します。

于 2010-03-09T01:20:09.523 に答える
0

ドキュメントから:

列挙は「安全」です。列挙中にコレクションを変更しようとすると、例外が発生するように、列挙子にはミューテーション ガードがあります。

基本的に、これは、Objective-C 2.0 で導入された高速列挙を使用して列挙している間、コレクション (配列など) にオブジェクトを追加/削除することは許可されていないことを意味します。そうすることでミューテーションガードが無効になるからです。

あなたの場合、コレクションはビュー階層に関連しています。この特定のコレクションにビューを追加または削除する場合は、高速列挙を使用しないでください。

于 2009-11-10T22:53:36.173 に答える
0

CALayer の -dealloc メソッド中にプロパティをクリアしようとすると、CALayers 内でこれが発生するのを見てきました。そのプロパティを変更すると、レイヤーの可視プロパティが誤って変更されるだけです。同じビューの -dealloc 中に、ビューの 1 つのプロパティを変更する何かを何らかの方法で行っているかどうかを確認できます。

于 2009-11-11T04:10:53.090 に答える