1

私はGameWindowController(のサブクラスNSWindowController)に次のメソッドを持っています:

- (void)windowWillClose:(NSNotification *)notification {
    AppDelegate *delegate = [NSApp delegate];
    [delegate removeGameWindowController:self];
}

AppDelegate の removeGameWindowController のコードは次のとおりです。

- (void)removeGameWindowController:(GameWindowController*)controller {
    [self.controllers removeObject:controller];
}

self.controllersすべての my を持つ NSMutableArrayGameWindowControllersです。

上記のコードには競合状態があるようです。EXC_BAD_ACCESSすべてのウィンドウを一度に閉じると、ほとんどの場合、ウィンドウを閉じるとランダムにクラッシュします。

私の推測では、ARC はウィンドウ コントローラーの割り当てを解除する前またはremoveGameWindowController:返すときに、ウィンドウにコントローラーへのポインターをぶら下げたままにしていると思われます。controller.window.windowController = nil;無駄に追加しようとしました。

何らかの理由で、https://stackoverflow.com/a/11782844/344544(BOOL)windowShouldClose:(id)senderで提案されているように代わりにデリゲート メソッドを使用すると機能しますが、終了時に呼び出されないため、受け入れられるソリューションではありません。

各ウィンドウが閉じられた後、コントローラーの配列からウィンドウコントローラーを確実に削除するにはどうすればよいですか? 呼び出される他のデリゲート メソッドや、ウィンドウが閉じた後に発生するサブスクライブできる NSNotification はありますか?

4

1 に答える 1

0

長い調査とデバッガーでの段階的な実行の後、問題の原因と考えられる解決策を見つけました。

ウィンドウ コントローラは、実際には、 が終了した後のある時点でremoveGameWindowController:NSWindow. スタックがウィンドウ自体の呼び出しに巻き戻される前にウィンドウが解放された場合、この特定のケースではダングリング ポインターであるcloseため、その関数の終了中にプログラムがクラッシュします。self

ウィンドウが閉じた後に通知を受け取る方法を見つけることができませんでしたが、そのようなアプローチでもまったく同じ問題が発生した可能性があります。

ウィンドウへの参照がスタックのどこにも残らないようにするために、配列からのウィンドウ コントローラーの削除をキューに入れ、実行ループの後続のイベントとして発生させました。

- (void)removeGameWindowController:(GameWindowController*)controller {
    [self.controllers performSelectorOnMainThread:@selector(removeObject:) withObject:controller waitUntilDone:NO];
}
于 2013-08-28T12:13:08.250 に答える