Core Dataと抽象エンティティを使用してマスター/ディテールインターフェイスを作成するにはどうすればよいですか?
-
06-07-2019 - |
質問
Appleには、単純なマスター/ディテールインターフェイスを作成するための素敵な小さなチュートリアルがあります。 Interface Builderは、Core Dataエンティティから自動的に生成します。ただし、単純な例よりも複雑なことをしようとしているため、しばらく動作させるのに苦労しています。
Core Dataドキュメントベースのアプリケーションがあります。このモデルには、抽象的なエンティティページと、ページのいくつかの具体的なサブエンティティが含まれます。すべてのページにはいくつかの共通の属性(" name"など)があり、それらはページで定義されています。明らかに、サブエンティティには固有の属性があります。
インターフェイスを使用して、ユーザーがマスターリスト(NSTableView)のすべての種類のページを表示できるようにします。ユーザーがページを選択すると、表示される詳細フィールドは、ページの種類によって異なります。
私が今持っているものは次のとおりです。
マスターリストが表示されるメインnibファイルと、ページに共通のすべてのフィールドがあります。特定のフィールドを持つページタイプごとにペン先があります。メインのnibファイルにはメインのNSArrayControllerがあり、NSTableViewにデータが入力されています。各ページ固有のペン先にもNSArrayControllerがあり、詳細フィールドを現在の選択の属性にバインドできます。 NSArrayControllersはすべて同じように構成されており、同じmanagedObjectContextと同じselectionIndexにすべてバインドされています。
私は、Aaron Hillegassの「Cocoa」の本で説明しているビュースワッピングの方法を使用しています。 NSTableViewSelectionDidChangeNotificationsに登録しました。NSTableViewSelectionDidChangeNotificationsを受け取ると、メソッドswitchViewを呼び出します。
switchViewは、現在選択されているオブジェクトを調べ、どのタイプのページであるかをチェックし、Hillegassの方法に従って適切なnibファイルにスワップします。
1つのタイプのページのみを追加する場合はすべて正常に機能しますが、2番目のタイプのページを追加するとすぐにこのエラーが発生します:
オブジェクトのキーパスselectionIndexesの値の設定エラー(バインドされたオブジェクトエンティティから:ページ、選択されたオブジェクトの数:1):[valueForUndefinedKey:]:エンティティNoColPageはキー側のキー値コーディングに準拠していません。
エラーの最後の部分は理にかなっています。間違ったペン先を表示しようとしてスタックしているため、このオブジェクトには存在しないフィールドにバインドしようとしています。
NSArrayControllersのすべてが同じ場所にバインドできるように、selectDocumentesフィールドをMyDocumentに追加しました。私はこれについて何日も苦しみました、そして、私はそれを理解することができません。アイデアはありますか?
それが役立つ場合は、こちらからダウンロードできるサンプルプロジェクトをご覧ください。プロジェクトからこの問題に関連するものだけを抽出して、新しいダミーアプリケーションに抽出しました。このダミーアプリケーションは、テストと操作に使用していました。
PS:Core Dataエンティティからマスター/ディテールインターフェイスを生成するInterface Builderのツールは、抽象エンティティに対しては期待どおりに機能しません。スーパーエンティティの属性のフィールドのみを作成します。
編集:ジョシュアは何かに取り組んでいると思いますが、残念ながら機能しません。同じ問題に直面し続けています。 -unbind:がキーパスではなく文字列定数を期待していることを理解できなかったため、最初は苦労していました。
いくつかのバリエーションを試しました。現在表示されているnibのアレイコントローラーを追跡します。現在表示されているページタイプを追跡し、別のページタイプを表示しようとしている場合にのみアンバインド/再バインドします...
コードの関連セクションです。
-(void) displayViewController: (ManagingVC *) vc withClass:(NSString*) className {
//Try to end editing
NSWindow *w = [box window];
BOOL ended = [w makeFirstResponder:w];
if (!ended) {
NSBeep();
return;
}
//The Managing View Controller's NSArrayController
NSArrayController* vcAc = [vc arrCont];
//if the page we're trying to switch to is NOT the same type as the current page we're displaying
//if it is, do nothing.
if (![currPageDisplayed isEqual:className]) {
//unbind the old view controller
ManagingVC *oldvc = [viewControllers objectForKey:className];
NSArrayController* oldsac = [oldvc arrCont];
[oldsac unbind:@"selectionIndexes"];
//bind the new view controller
[vcAc bind:@"selectionIndexes" toObject:self withKeyPath:@"selectionIndexes" options:nil];
currPageDisplayed = className;
NSView *v = [vc view];
//display the new view in an NSBox in the main nib
[box setContentView:v];
}
}
解決 2
各NIBのアレイコントローラーを同期させるために時間をかけすぎた後、私はそのアプローチをあきらめました。私のために働いた唯一のことは、メインのペン先に表示されるGUI要素とそのバインディングをプログラムで制御することです。これは、他のペン先を削除することを意味します。これは、2つ以上のテキストフィールドで作業している場合、実際には持続可能なソリューションではありませんが、今のところ私には有効です。
ビューを切り替える前にバインド解除のジョシュアのアドバイスに従いますが、現在はテキストフィールドをarrayController.selection.whateverKeyにのみバインドしています
他のヒント
問題は、ペン先の配列コントローラーをドキュメントの選択にバインドしたままにしておくことです。これにより、選択したアイテムを表現しようとします。
これを試してください:
- ペン先のバインディングを削除します。
- 新しいビューを追加する前に、コードでバインディングを接続します。
- 古いビューを削除する前に、コード内のバインディングを切断します。
これにより、すべてが幸せになります。