如何自动选择插入到 NSOutlineView 中的项目核心数据

发布于 2024-11-03 02:10:49 字数 3750 浏览 4 评论 0原文

我有一个 NSTreeController 绑定了一个绑定到实体的 NSArrayController ,并将树绑定到了 NSOutlineView 。现在,当单击“添加”按钮时,我想向 TreeController 添加一个新实体,选择该实体,然后突出显示它以进行编辑。如果我调用 [arrayController add] ,插入是异步的,我无法知道新对象是哪个,因为大纲视图不会自动选择新行。所以我只能以编程方式插入新实体。因此,addButtonoutlineViewController 上调用createNewGroup(见下文)。

同样,插入新实体似乎不是一个同步过程。我无法在 currentObject = [NSEntityDescription... 之后的下一行的 NSOutlineView 中找到它。我在重新加载数据后确实尝试过。所以我只能观察数组控制器中的值变化。大多数情况下,这种方法有效,但有时却行不通。这是处理此类事情的正确方法吗?

- (void) createNewGroup:(id)sender {
    NSInteger row = [myOutlineView selectedRow];
    if(row == -1) {
        [groupsController addObserver:self 
                           forKeyPath:IR_GROUPS_KEYPATH 
                              options:NSKeyValueObservingOptionInitial 
                              context:IR_GROUPS_CONTEXT];
        currentObject = [NSEntityDescription insertNewObjectForEntityForName:@"Group" 
                                                      inManagedObjectContext:appDelegate.managedObjectContext];
        return;
    }
    if([myOutlineView levelForRow:row] != 0) return;
    [subGroupsController addObserver:self 
                          forKeyPath:IR_GROUPS_KEYPATH 
                             options:NSKeyValueObservingOptionInitial 
                             context:IR_SUBGROUPS_CONTEXT];
    NSManagedObject *parent = [[myOutlineView itemAtRow:row] representedObject];
    currentObject = [NSEntityDescription insertNewObjectForEntityForName:@"Group" 
                                                            inManagedObjectContext:appDelegate.managedObjectContext];
    [currentObject setValue:parent forKey:@"parent"];
}

- (void) observeValueForKeyPath:(NSString *)keyPath 
                       ofObject:(id)object 
                         change:(NSDictionary *)change 
                        context:(void *)context {

    if([keyPath isEqualToString:IR_GROUPS_KEYPATH]) {
        if(currentObject == nil) return;
        [myOutlineView noteNumberOfRowsChanged];
        NSString *ctx = (NSString *) context;
        if([ctx isEqualToString:IR_GROUPS_CONTEXT]) {

            NSInteger length = [myOutlineView numberOfRows];
            NSInteger index;
            for(index = 0; index < length; index++) {
                id item = [myOutlineView itemAtRow:index];
                if(currentObject == [item representedObject]) {
                    // We found the new object:
                    NSIndexSet *indices = [NSIndexSet indexSetWithIndex:index];
                    [myOutlineView selectRowIndexes:indices byExtendingSelection:NO];
                    [myOutlineView editColumn:0 row:index withEvent:nil select:YES];
                    currentObject = nil;
                    return;
                }
            }
            //[groupsController removeObserver:self forKeyPath:nil];

        } else if([ctx isEqualToString:IR_SUBGROUPS_CONTEXT]) {
            NSTreeNode *parent = [myOutlineView itemAtRow:[myOutlineView selectedRow]];
            [myOutlineView expandItem:parent];
            NSInteger length = [myOutlineView numberOfRows];
            NSInteger index;
            for(index = 0; index < length; index++) {
                id item = [myOutlineView itemAtRow:index];
                if(currentObject == [item representedObject]) {
                    NSIndexSet *indices = [NSIndexSet indexSetWithIndex:index];
                    [myOutlineView selectRowIndexes:indices byExtendingSelection:NO];
                    [myOutlineView editColumn:0 row:index withEvent:nil select:YES];
                    currentObject = nil;
                    return;
                }
            }
        }
    }
}

I have an NSTreeController bound an NSArrayController bound to an entity and the tree bound to an NSOutlineView. Now, when an "add" button is clicked, I would like to add a new entity to the treeController, select the entity, and highlight it for editing. If I call [arrayController add], the insertion is asynchronous and I have no way of knowing which the new object is since the outline view does not select new rows automatically. So I am left with inserting the new Entity programatically. So addButton calls createNewGroup on a outlineViewController (see below).

Again, inserting a new entity does not seem to be a synchronous process. I can't locate it in the NSOutlineView in the next line after currentObject = [NSEntityDescription.... And I did try after reloading the data. So I am left with observing the value changes in the array controller. This sort of works, most of the time, but occasionally it does not. Is this the right approach to this sort of thing?

- (void) createNewGroup:(id)sender {
    NSInteger row = [myOutlineView selectedRow];
    if(row == -1) {
        [groupsController addObserver:self 
                           forKeyPath:IR_GROUPS_KEYPATH 
                              options:NSKeyValueObservingOptionInitial 
                              context:IR_GROUPS_CONTEXT];
        currentObject = [NSEntityDescription insertNewObjectForEntityForName:@"Group" 
                                                      inManagedObjectContext:appDelegate.managedObjectContext];
        return;
    }
    if([myOutlineView levelForRow:row] != 0) return;
    [subGroupsController addObserver:self 
                          forKeyPath:IR_GROUPS_KEYPATH 
                             options:NSKeyValueObservingOptionInitial 
                             context:IR_SUBGROUPS_CONTEXT];
    NSManagedObject *parent = [[myOutlineView itemAtRow:row] representedObject];
    currentObject = [NSEntityDescription insertNewObjectForEntityForName:@"Group" 
                                                            inManagedObjectContext:appDelegate.managedObjectContext];
    [currentObject setValue:parent forKey:@"parent"];
}

- (void) observeValueForKeyPath:(NSString *)keyPath 
                       ofObject:(id)object 
                         change:(NSDictionary *)change 
                        context:(void *)context {

    if([keyPath isEqualToString:IR_GROUPS_KEYPATH]) {
        if(currentObject == nil) return;
        [myOutlineView noteNumberOfRowsChanged];
        NSString *ctx = (NSString *) context;
        if([ctx isEqualToString:IR_GROUPS_CONTEXT]) {

            NSInteger length = [myOutlineView numberOfRows];
            NSInteger index;
            for(index = 0; index < length; index++) {
                id item = [myOutlineView itemAtRow:index];
                if(currentObject == [item representedObject]) {
                    // We found the new object:
                    NSIndexSet *indices = [NSIndexSet indexSetWithIndex:index];
                    [myOutlineView selectRowIndexes:indices byExtendingSelection:NO];
                    [myOutlineView editColumn:0 row:index withEvent:nil select:YES];
                    currentObject = nil;
                    return;
                }
            }
            //[groupsController removeObserver:self forKeyPath:nil];

        } else if([ctx isEqualToString:IR_SUBGROUPS_CONTEXT]) {
            NSTreeNode *parent = [myOutlineView itemAtRow:[myOutlineView selectedRow]];
            [myOutlineView expandItem:parent];
            NSInteger length = [myOutlineView numberOfRows];
            NSInteger index;
            for(index = 0; index < length; index++) {
                id item = [myOutlineView itemAtRow:index];
                if(currentObject == [item representedObject]) {
                    NSIndexSet *indices = [NSIndexSet indexSetWithIndex:index];
                    [myOutlineView selectRowIndexes:indices byExtendingSelection:NO];
                    [myOutlineView editColumn:0 row:index withEvent:nil select:YES];
                    currentObject = nil;
                    return;
                }
            }
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

深空失忆 2024-11-10 02:10:49

如果你使用 NSTreeController (的子类)来为你的outlineView提供内容,那就非常简单了。您可以在代码或 Interface Builder 中创建一个按钮,并将目标绑定到 insert: 以添加元素或设置 remove: 以删除它。在代码中,它看起来像这样:

[aButton bind:NSTargetBinding 
     toObject:aController 
  withKeyPath:keyPathToTreeController
    options:[NSMutableDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSConditionallySetsEnabledBindingOption,
                             @"insert:", NSSelectorNameBindingOption,
                             nil]];

选择新对象是由树控制器处理的。再次,在代码中:

[aTreeController setSelectsInsertedObjects:YES];

在 IB 中,这是一个您需要选中的复选框。哦,还有 addChild:。让绑定发挥其魔力。

If you use (a subclass of) NSTreeController to provide the content for you outlineView, it is very simple. You create a button, either in code or in Interface Builder, and set bind the target to insert: to add an element or remove: to delete it. In code it would look like this:

[aButton bind:NSTargetBinding 
     toObject:aController 
  withKeyPath:keyPathToTreeController
    options:[NSMutableDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSConditionallySetsEnabledBindingOption,
                             @"insert:", NSSelectorNameBindingOption,
                             nil]];

Selecting the new object is handled by the treeController. Again, in code:

[aTreeController setSelectsInsertedObjects:YES];

In IB, it's a checkbox that you need to check. Oh, there's also addChild:. Let the bindings do their magic.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文