したがって、アプリケーションで NSOutlineView を使用して、より適切な名前がないため、特定の階層を表示したいと考えています。説明するために、コードでどのように表示されるかを次に示します。表示したいオブジェクトで使用されるいくつかのメソッドを宣言するプロトコルがあります。
@protocol OutlineViewItem <NSObject>
@required -(BOOL)hasChildren; //Tells whether the object has children
@required -(NSInteger)numberOfChildren; //returns 0 if none or number of children
@required -(id)getChildren; //return NSMutableArray containing children
@required -(NSString*)getDisplayableName; //returns a string that would be displayed in NSOutlineView
@end
お察しのとおり、これらの方法により、私の作業が少し楽になるはずです。
次に、オブジェクトの次の階層があります(すべてがそのプロトコルを実装しています)->
メイン アプリケーションには、SubprojectItem クラス インスタンスの NSMutableArray を含む Subproject クラス インスタンスの NSMutableArray を含む Project クラスの 1 つのインスタンスが含まれます。
Project クラスでこれらのプロトコル メソッドを使用する方法の例 (サブプロジェクトは、前述の NSMutableArray です。
-(BOOL)hasChildren{
if(subprojects == nil || [subprojects count] < 1){
return NO;
}
return YES;
}
-(NSInteger)numberOfChildren{
if(subprojects == nil){
return 0;
}
return [subprojects count];
}
-(id)getChildren{
return subprojects;
}
-(NSString*)getDisplayableName{
return name;
}
Subproject および SubprojectItem クラスは、これらのメソッドを同様の方法で実装します。
私のアプリケーションでは、メイン ウィンドウ クラス (ProjectWindow) を定義して NSOutlineViewDataSource および Delegate プロトコルを実装し、NSOutlineView のデータ ソースとデリゲートを ProjectWindow にバインドしました。
ProjectWindowClass では、次のようにメソッドを実装しました。
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item
{
return item == nil ? project : [item getChildren];
//if I understand it correctly, it return the children of a given node.
//if item is nil, it should return the root, that is, project, or the children of item.
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item
{
return item == nil? YES : [item hasChildren];
//Same as above: project is expendable, other nodes can be expanded if contain children
}
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item
{
return item == nil? 1 : [item numberOfChildren];
//Same as above: there's 1 project, or it returns num of children;
}
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item
{
return item == nil ? @"ROOT" : [item getDisplayableName];
//I think that's what is going to be displayed in NSOutlineView, next to the expendable arrow
}
ただし、実行しようとすると、次の例外が発生します。
2013-08-23 22:45:12.930 myProject[1903:303] -[__NSArrayM hasChildren]: unrecognized selector sent to instance 0x101a16f30
NSOutlineViewDataSource 全体を理解していれば、item == nil で要求された場合はルート アイテムを返し、item != nil の場合は item の子を返す必要があります。しかし、その通りだと思っていたのに、うまくいかず、アプリがハングアップしてしまいます。
では、意図したとおりに機能させるには、これらすべてのデータ ソース メソッドをどのように実装すればよいでしょうか?