代码之家  ›  专栏  ›  技术社区  ›  PerfectGamesOnline.com

nsOutlineView拖放(在项目旁边)不适用于复杂项目

  •  0
  • PerfectGamesOnline.com  · 技术社区  · 7 年前

    我的基本示例适用于由标准objc类表示的项。 参见初始化 self.list 在下面的示例中:

    - (void) updateViews;
    {
        NSDictionary *firstParent = [NSDictionary dictionaryWithObjectsAndKeys:@"Foo",@"parent",[NSArray arrayWithObjects:@"Foox",@"Fooz", nil],@"children", nil];
        NSDictionary *secondParent = [NSDictionary dictionaryWithObjectsAndKeys:@"Bar",@"parent",[NSArray arrayWithObjects:@"Barx",@"Barz", nil],@"children", nil];
        self.list = [NSArray arrayWithObjects:firstParent,secondParent, nil];
    
        self.outlineView.delegate = self;
        self.outlineView.dataSource = self;
    
    
        // Enable Drag and Drop
        [self.outlineView registerForDraggedTypes:@[LOCAL_REORDER_PASTEBOARD_TYPE]];
    }
    
    
    #pragma mark - NSOutlineViewDelegate
    
    - (BOOL) outlineView:(NSOutlineView*)outlineView isItemExpandable:(id)item
    {
        if ([item isKindOfClass:[NSDictionary class]]) {
            return YES;
        }
        else {
            return NO;
        }
    }
    
    - (NSInteger) outlineView:(NSOutlineView*)outlineView numberOfChildrenOfItem:(id)item
    {
        if (item == nil) { //item is nil when the outline view wants to inquire for root level items
            return [self.list count];
        }
    
        if ([item isKindOfClass:[NSDictionary class]]) {
            return [[item objectForKey:@"children"] count];
        }
    
        return 0;
    }
    
    - (id) outlineView:(NSOutlineView*)outlineView child:(NSInteger)index ofItem:(id)item
    {
        if (item == nil) { //item is nil when the outline view wants to inquire for root level items
            return [self.list objectAtIndex:index];
        }
    
        if ([item isKindOfClass:[NSDictionary class]]) {
            return [[item objectForKey:@"children"] objectAtIndex:index];
        }
    
        return nil;
    }
    
    - (NSView*) outlineView:(NSOutlineView*)outlineView viewForTableColumn:(NSTableColumn*)tableColumn item:(id)item
    {
        NSTableCellView *result = [outlineView makeViewWithIdentifier:@"DataCell" owner:self];
    
        NSString *txt = nil;
        if ([item isKindOfClass:[NSDictionary class]]) {
            txt = [item objectForKey:@"parent"];//[NSString stringWithFormat:@"%i kids", [[item objectForKey:@"children"] count]];
        }
        else {
            txt = str(item);
        }
    
        result.textField.stringValue = txt;
        return result;
    }
    
    - (BOOL) outlineView:(NSOutlineView*)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pasteboard 
    {
        [pasteboard declareTypes:[NSArray arrayWithObject:LOCAL_REORDER_PASTEBOARD_TYPE] owner:self];
        [pasteboard setData:[@"just a test - not yet implemented" dataUsingEncoding:NSUTF8StringEncoding] forType:LOCAL_REORDER_PASTEBOARD_TYPE];
        return YES;
    }
    
    - (NSDragOperation) outlineView:(NSOutlineView*)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(NSInteger)index 
    {
        NSUInteger op = NSDragOperationNone;
        if (index != NSOutlineViewDropOnItemIndex){
            op = NSDragOperationMove;
        }
        return op;
    }
    

    拖放按预期工作。

    enter image description here

    一旦我修改了 child:(NSInteger)index ofItem:(id)item 方法返回我自己类的复杂项,特别是 TreeItem 则拖放仅允许:

    1. 放置项目

    enter image description here

    1. 放置在父项旁边

    enter image description here

    但是,第一张图片中显示的叶项旁边的放置是不可能的。有什么线索吗?

    我还要添加不工作的复杂项的示例代码。 故事板和DragDrop代码对于这两种情况都是相同的。

    #define LOCAL_REORDER_PASTEBOARD_TYPE @"LOCAL_REORDER_PASTEBOARD_TYPE"
    #define str(...) [@[__VA_ARGS__] componentsJoinedByString:@""]
    
    @interface TreeItem : NSObject
    @property (nonatomic) NSArray<TreeItem*> *children;
    @property (nonatomic) NSString *name;
    + (nonnull instancetype) itemWithName:(nonnull NSString*)name;
    @end
    
    @implementation TreeItem
    + (nonnull instancetype) itemWithName:(nonnull NSString*)name;
    {
        TreeItem *obj = [[self alloc] init];
        obj.name = name;
        return obj;
    }
    - (NSArray<TreeItem*>*) children;
    {
        return self.name.length > 3 ? nil : @[
            [TreeItem itemWithName:str(self.name, @"x")],
            [TreeItem itemWithName:str(self.name, @"z")],
        ];
    }
    @end
    
    @interface SampleVC ()
    @property (weak) IBOutlet NSOutlineView *outlineView;
    @property (strong) NSArray<TreeItem*> *treeList;
    @end
    
    @implementation SampleVC
    
    - (void) updateViews;
    {
        self.treeList = @[
            [TreeItem itemWithName:@"Foo"],
            [TreeItem itemWithName:@"Bar"],
        ];
        self.outlineView.delegate = self;
        self.outlineView.dataSource = self;
        [self.outlineView reloadData];
        [self.outlineView registerForDraggedTypes:@[LOCAL_REORDER_PASTEBOARD_TYPE]];
    }
    
    - (BOOL) outlineView:(NSOutlineView*)outlineView isItemExpandable:(id)item
    {
        return item == nil ? YES : ((TreeItem*)item).children != nil;
    }
    
    - (NSInteger) outlineView:(NSOutlineView*)outlineView numberOfChildrenOfItem:(id)item
    {
        return item == nil ? self.treeList.count : (((TreeItem*)item).children != nil ? ((TreeItem*)item).children.count : 0);
    }
    
    - (id) outlineView:(NSOutlineView*)outlineView child:(NSInteger)index ofItem:(id)item
    {
        return item == nil ? [self.treeList objectAtIndex:index] : ((TreeItem*)item).children[index];
    }
    
    - (NSView*) outlineView:(NSOutlineView*)outlineView viewForTableColumn:(NSTableColumn*)tableColumn item:(id)item
    {
        NSTableCellView *result = [outlineView makeViewWithIdentifier:@"DataCell" owner:self];
        result.textField.stringValue = ((TreeItem*)item).name;
        return result;
    }
    @end
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   Willeke    7 年前

    大纲视图找不到子级的行并在视图顶部绘制下拉式指示器。 NSOutlineView rowForItem: 不能工作,如果 TreeItem 返回新数组 特雷特姆 每次 - (NSArray<TreeItem*>*) children; 被称为。