nscollectionViewはCoreDataと互換性があります
-
12-10-2019 - |
質問
更新:このスレッドは、コレクションビューの代表されるオブジェクトがnsmanagedObjectsである場合、nscollectionViewのバグを識別します。バグは次のようにトリガーされます。
(a)nsarrayControllerからオブジェクトを削除する(b)削除後、nscollectionViewがアニメーションを終了する前に、関連するnsmanagedObjectContextを保存します。
GitHubでのこれらのプロジェクトは、問題を示しています。
https://github.com/artifacts/nscollectionviewcoredatabughttps://github.com/iracooke/coredatacollectionviewcrashing
以下の元の質問
Core-DataエンティティのNSARRAYCONTROLLERの配置にバインドされたコンテンツバインディングを備えたNSCOLlectionViewのセットアップがあります。私のコレクションアイテムビュー(NSCOLLECTIONVIEWビューのプロトタイプ)では、CollectionViewアイテムのObjectを介してCore-Dataエンティティにbulingしているいくつかのコントロールがあります。
ほとんどの場合、これは大丈夫です。
ArrayControllerからエンティティを削除しようとすると、objc_exceptionに遭遇します。私は単に呼び出してこれらのエンティティを削除します。
[myArrayController removeObject:managedObjectToDelete];
残念ながら、これを行うと、「CoreDataが障害を満たすことができませんでした」エラーを頻繁に取得します。
例外がスローされたときのコールスタックの検査では、nscollectionViewが_endofanimationメソッドを受信したときにクラッシュが発生することが明らかになります。これにより、バインディングを解除することで他の方法を開始します(私の見解では、コントロールを持つ私のエンティティのプロパティの可能性があります)。
さらに1つの情報は、私が協力しているエンティティには、私のモデルの他のエンティティとの関係がないことです。
次の問題が発生しているかのように見えます。
- nsarrayControllerからオブジェクトを削除すると、コンテキストからターン削除されます。
- コンテキストからの削除の後、オブジェクトは障害に変わります
- nscollectionViewは、オブジェクトへの参照を保持しています(現在の障害)。アニメーションの最後にそれらをきれいにしようとします(バインディングなど)。
- nscollectionViewがオブジェクトへのバインディングをクリーンアップしようとすると、コアデータがオブジェクトの障害を発射しようとします(用語がすぐに入ったことを願っています)。オブジェクトがまだディスクに保存されていないため、これによりエラーが発生します。
私がこれを防ぐために考えることができる唯一の方法は、削除前にストア内のオブジェクトを(保存することによって)持続することです。これは機能しますが、1回のラウンドの削除が完了する前に再び保存する必要があるため、ハッキッシュな方法でのみです...そして、アニメーション中にエラーが発生します。同じエラーが再び発生します。
これは、nscollectionViewを入力するためにコアデータバックされたnsarraycontrollerを使用できないことを意味しますか?そうでない場合、私は何を間違えていますか?この問題を回避するより良い方法はありますか?
解決
直接でありながら退屈な答え:コアデータをバックしたNSARRAYCONTROLLERがNSCOLLECTIONVIEWを設定できることを確認できます。コレクションNSViewアイテムの異なるGUIオブジェクトが生成された「コレクションビューアイテム」にバインドされ、パスに沿ったさまざまなコアデータオブジェクトを参照します。 NSARRAYCONTROLLER WORKS(アニメーションを無料で)のプログラムで削除(および再注文)します。
おそらく、コレクションビュー内のいくつかのバインディングやその他の依存関係が問題を引き起こしていますか?または、管理されたオブジェクトコンテキストに関するスレッドの問題?
他のヒント
対応するArrayControllerを指す(assional)プロパティをCollectionItemに追加することで、この問題を回避できます。
このプロパティは、 - [yournscollectionviewsubclass newitemwithrepresentededObject:]に設定できます。
次に、各アイテムに配置されたオブジェクトを観察できます。変更とitem.representededObjectがArricaledObjectsに含まれていない場合、itemに設定します。私のテスト(10.6.8)では、CoreDataがオブジェクトを障害に変える前に、これにより結合のクリーンアップがトリガーされます。 (私のオブジェクトには関係があり、アイテムビューにはそれらにバインディングがあります)。
ところで:この問題は、アニメーション中の保存に限定されません。組み合わせも元に戻す/やり直し/保存することもできます。
私はアイテム内の観察を始めるのに良い場所を探していましたが、私が思いついたのはコピーウィスゾーンだけでした。 (-awakefromnibは最初のアイテムに対してのみ呼び出されます。-Viewは早すぎます)。
したがって、私は(しぶしぶ)-newitemwithrepresentedededobjectで観察を開始することを決定し、アイテムの-deallocでそれを停止しました。
また、アイテムビュー内のオブジェクトによってトリガーされるコントロールやその他のアクションに注意する必要があります。迅速にクリックすることにより、おそらくマウスの下でアニメーション化するまだ反応するボタンが扱われることになります。私の解決策は、ObjectをNILに設定するときにコントロールを無効にすることです。 ymmv。
これが私のオブザーバーコードです:
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if( object == self.arrayController && [keyPath isEqualToString: @"arrangedObjects"] ) {
if( NO == [self.arrayController.arrangedObjects containsObject: self.representedObject] ) {
self.representedObject = nil;
for(NSView *subview in [self.view subviews]) {
if( [subview isKindOfClass: [NSControl class]] ) {
[(NSControl *)subview setEnabled: NO];
}
}
}
} else {
[super observeValueForKeyPath:keyPath ofObject: object change:change context:context];
}
}