2

NSOutlineView にドラッグ アンド ドロップを実装しようとしていますが、サンプル コード、チュートリアル、その他の SO に関する質問のいずれも、私の状況ではうまくいかないようです。コンテンツが NSTreeController にバインドされた NSOutlineView があります。ツリー コントローラのコンテンツ配列は、同じタイプの子オブジェクトを持つカスタム オブジェクトの NSMutableArray にバインドされます。アウトライン ビューでは、階層内の任意のレベルでオブジェクトを追加および削除できます。ここまでは順調ですね。

ドラッグ アンド ドロップを実装するために、アウトライン ビューのデータソースとして機能する NSObject サブクラスを作成しました。Stack Overflow で見つけたサンプル コードと投稿に基づいて、いくつかのメソッドを実装しました。ドラッグを開始できますが、ドロップすると、outlineView: acceptDrop: item: childIndex: が呼び出されますが、childIndex: を除くすべての値は nil です。childIndex の値は、配列内のドロップ位置のインデックスを示していますが、階層内のどのノードにいるのかは示していません。

OutlineView: acceptDrop: ... で渡される他のすべての値は nil であると想定しています。これは、dataSource を完全に実装していないためです。ドラッグ アンド ドロップ操作を制御するためだけに使用しています。ドラッグを開始するときに、ペーストボード情報をさらに設定する必要がありますか? ドロップが発生したときに自分がいるノードを確認するにはどうすればよいですか? OutlineView:acceptDrop: のすべての値が ... nil なのはなぜですか?

以下は、アウトライン ビュー dataSource の実装です: \ @implementation TNLDragController

- (void)awakeFromNib {
    [self.titlesOutlineView registerForDraggedTypes:[NSArray arrayWithObject:@"Event"]];
}

- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard {
    NSLog(@"starting a drag");

    NSString *pasteBoardType = @"Event";
    [pboard declareTypes:[NSArray arrayWithObject:pasteBoardType] owner:self];

      return YES;
}

- (NSDragOperation)outlineView:(NSOutlineView *)outlineView
                  validateDrop:(id < NSDraggingInfo >)info
                  proposedItem:(id)item
            proposedChildIndex:(NSInteger)index {
    NSLog(@"validating a drag operation");
    return NSDragOperationGeneric;
}

- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id < NSDraggingInfo >)info item:(id)item childIndex:(NSInteger)index {
    NSLog(@"accepting drag operation");
    //todo: move the object in the data model;
    NSIndexPath *path = [self.treeController selectionIndexPath]; // these three values are nil too.
    NSArray *objects = [self.treeController selectedObjects];
    NSArray *nodes = [self.treeController selectedNodes];
    return YES;
}

// This method gets called by the framework but the values from bindings are used instead
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
     return NULL;
}

/*
 The following are implemented as stubs because they are required when
 implementing an NSOutlineViewDataSource. Because we use bindings on the
 table column these methods are never called. The NSLog statements have been
 included to prove that these methods are not called.
 */
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
     NSLog(@"numberOfChildrenOfItem");
     return 1;
}

- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
     NSLog(@"isItemExpandable");
     return YES;
}

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
     NSLog(@"child of Item");
     return NULL;
}
@end
4

1 に答える 1

0

この質問で説明した実装は、実際には問題なく機能していましたが、機能しているかどうかを判断しようとしたときに初歩的なミスを犯しました。- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id < NSDraggingInfo >)info item:(id)item childIndex:(NSInteger)indexメソッドに渡された値を調べるために、ブレークポイントを設定しました。私は ARC を使用していますが、メソッド内で値が参照されなかったため、ARC はそれらを保持せず、デバッガーで使用できなくなりました!

于 2014-01-05T06:52:24.423 に答える