Appleには、簡単なマスター/詳細インターフェイスを作成するためのちょっとしたチュートリアルがあります。Interface Builderは、CoreDataエンティティから自動的に生成します。しかし、私は単純な例よりも複雑なことをしようとしていて、それを機能させるためにしばらく苦労してきました。
CoreDataドキュメントベースのアプリケーションがあります。モデルには、抽象エンティティのページと、ページのいくつかの具体的なサブエンティティが含まれています。すべてのページにはいくつかの共通の属性(「名前」など)があり、それらはページで定義されています。明らかに、サブエンティティには固有の属性があります。
ユーザーがマスターリスト(NSTableView)内のすべてのタイプのページを表示できるようにするインターフェイスが必要です。ページを選択すると、表示される詳細フィールドは、ページの種類によって異なります。
これが私が今持っているものです:
マスターリストが表示されるメインのnibファイルと、ページに共通するすべてのフィールドがあります。各ページタイプには、特定のフィールドを持つペン先があります。メインのnibファイルにメインのNSArrayControllerがあり、NSTableViewにデータが入力されています。各ページ固有のペン先にもNSArrayControllerがあるので、詳細フィールドを現在の選択の属性にバインドできます。すべてのNSArrayControllerは同じように構成されており、すべて同じmanagedObjectContextと同じselectionIndexesにバインドされています。
私はアーロンヒレガスのビュースワッピングの方法を使用しています。彼は彼のココアの本で説明しています。そこで、NSTableViewSelectionDidChangeNotificationsに登録しました。これを受け取ると、メソッドswitchViewが呼び出されます。
switchViewは、現在選択されているオブジェクトを調べ、それがどのタイプのページであるかを確認し、Hillegassの方法に従って適切なnibファイルをスワップします。
1つのタイプのページのみを追加するとすべて正常に機能しますが、2番目のタイプのページを追加するとすぐに、次のエラーが発生します。
オブジェクトのキーパスselectionIndexesの値の設定エラー(バインドされたオブジェクトエンティティから:ページ、選択されたオブジェクトの数:1):[valueForUndefinedKey:]:エンティティNoColPageは、キー側のキー値コーディングに準拠していません。
エラーの最後の部分は理にかなっています。間違ったペン先を表示しようとしてスタックしているため、このオブジェクトには存在しないフィールドにバインドしようとしています。
すべてのNSArrayControllerが同じ場所にバインドできるように、selectionIndexesフィールドをMyDocumentに追加しました。私はこれについて何日も苦しんでいて、それを理解することができません。何か案は?
それが役立つ場合は、ここにダウンロードできるサンプルプロジェクトがあります。この問題に関連するものだけをプロジェクトから新しいダミーアプリケーションに抽出し、それをテストして試してみました。
PS:CoreDataエンティティからマスター/詳細インターフェイスを生成するためのInterfaceBuilderのツールは、抽象エンティティの場合とは異なります。スーパーエンティティの属性のフィールドのみを作成します。
編集:ジョシュアは何かに取り組んでいると思いますが、残念ながらそれは機能しません-私は同じ問題に遭遇し続けます。-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];
}
}