1

NSArrayControllerのrearrangeObjects関数に問題があります-この関数はいくつかのバックグラウンドトレッドから呼び出され、アプリがエラーでクラッシュすることがあります:'endUpdatesがbeginUpdatesなしで呼び出されました'。

arrayControllerが現在オブジェクトを再配置しているかどうかを検出し、次の再配置をキューなどに追加したり、現在の再配置をキャンセルして新しく実行したりするにはどうすればよいですか?

この問題の別の解決策があるかもしれませんか?

追加された編集コード:

TableController implementation:

- (void)setContent{//perfoms on main thread
     //making array of content and other functions for setting-up content of table
     //...
     //arrayController contains objects of MyNode class
     //...
     //end of setting up. Call rearrangeObjects
     [arrayController rearrangeObjects];
}

- (void)updateItem:(MyNode *)sender WithValue:(id)someValue ForKey:(NSString *)key{
     [sender setValue:someValue forKey:key];
     [arrayController rearrangeObjects];//exception thrown here
}

MyNode implementation:

- (void)notifySelector:(NSNotification *)notify{
     //Getted after some processing finished
     id someValue = [notify.userInfo objectForKey:@"observedKey"];
     [delegate updateItem:self WithValue:someValue ForKey:@"observedKey"];
}
4

3 に答える 3

4

そうしないでください。AppKit (にNSArrayController属する) は、一般的にスレッドセーフではありません。代わりに、 を使用-performSelectorOnMainThread:...して UI (を含む) を更新しますNSArrayController。常にメイン スレッドで更新を行います。

于 2012-08-23T17:14:18.177 に答える
0

ジョシュアとダンの解決策は正しいです。バックグラウンド スレッドでモデル オブジェクトに対して操作を実行している可能性が高く、それがアレイ コントローラーに触れ、したがってテーブルに触れます。

NSTableView 自体はスレッドセーフではありません。「beginUpdates/endUpdates」ペアを追加するだけで、競合状態を少し回避できます。ただし、Fin が指摘したように、パフォーマンス上の理由から 2 つの更新を行うのは良いことかもしれませんが、クラッシュには役立たないでしょう。

クラッシュの原因を見つけるには、![NSThread currentThread].mainThread のコードにいくつかのアサーションを追加します。特に、アレイ コントローラーのコンテンツに触れる前の任意の場所に追加します。これは、問題を特定するのに役立ちます。または、NSTableView をサブクラス化し、オーバーライド-numberOfRows(変更時に頻繁に呼び出される) や super の呼び出しなど、どこかのキーにアサーションを追加します。

-corbin
AppKit/NSTableView

于 2016-05-02T15:22:53.370 に答える
-1

UIの初期化の最初にこれを追加することでこれを解決しました

[myTableView beginUpdates];

そして、永続ストアが完全にロードされた後の最後に:

[myTableView endUpdates];

これにより、MOC からすべての読み込みを常にリロードする必要がないため、アプリの起動も大幅に改善されます。

于 2013-03-21T13:16:35.410 に答える