1

我有一个绑定到支持核心数据的 NSArrayController 的 NSPopupButton。NSPopupButton 的选择也绑定到一个核心数据支持项。绑定大致如下:

核心数据实体的 NSArray 'A' --> 数组控制器
数组控制器 --> NSPopupButton.contentValues.arrangedObjects.name

核心数据实体的 NSArray 'B' --> 数组控制器
数组控制器 --> NSPopupButton.selectedObject.methodOnObject.name

selectedObject 上有一个方法,该方法查找一个 ID,该 ID 找到一个对象并返回该对象,如下所示:

-(MyWidget *)selectedWidget {

    return [MyCunningLookupMethod widgetForID:[[self widgetID] intValue]];
}

并且以另一种方式设置对象非常简单:

-(void)setSWidget:(MyWidget *)anObj {

    [self setWidgetID:[anObj uid]];
}

大多数情况下,对象与可用 contentValues 列表中的对象匹配。但是,有时所选对象的 ID 为 0 - 在这种情况下,我想在可用列表中显示一个名为“未选择”的选项。如果对象 ID 为 0,我可以轻松地完成发回不同的对象(或什么都没有)。

我可以用“无选择占位符”来处理这个问题,但是一旦用户选择了其他项目之一,未选择的占位符就会从列表中删除。

我希望能够为用户提供选择项目的能力,或者选择不选择项目(即将其设置回“未选择”)。每次选择更改时,没有通过遍历我从核心数据中获得的数组以编程方式创建整个 NSPopupMenu,有没有办法将一个菜单项插入到列表中,表示用户始终可以使用的未选择状态?

我已经考虑将一个实体对象添加到核心数据存储中,该对象具有所有基于 0 的值,但名称除外,即“未选择”。然而,这只是感觉不是正确的做事方式,并且实际上提出了一些其他问题,即在存储中存在实际上没有任何数据相关性的空对象。

与往常一样,我们将不胜感激任何和所有的帮助。

解决方案

好吧,我并没有完全按照Hobbes the Tige发布的内容进行操作,但这几乎使我到达了需要的位置。我最终创建了一个方法,而不是在 IB 中绑定,该方法允许我在选择更改时将我的对象数组发送到父数组或发起更改的用户活动。然后该方法简单地使用适当的核心数据实体信息更新 NSPopupButton,并且仍然允许我向我们的 IB 绑定匹配对象的 selectedTag。

这是方法

+(void)createContentsForPopup:(NSPopUpButton *)aPopupButton
                withArray:(NSArray *)anObjectArray 
           addNotSelected:(BOOL)aFlag {

    [aPopupButton removeAllItems];

    if (aFlag) {    

        if (!anObjectArray || [anObjectArray count] == 0) {

           [aPopupButton addItemWithTitle:@"--- Not available ---"];
           [[aPopupButton itemAtIndex:0] setTag:0];

           return;
        }

        [aPopupButton addItemWithTitle:@"--- Not selected ---"];
        [[aPopupButton itemAtIndex:0] setTag:0];
    }

    NSSortDescriptor * sd = [NSSortDescriptor sortDescriptorWithKey:@"name"
                                                          ascending:YES];

    [anObjectArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sd]];

    for (id anObject in anObjectArray) {

        [aPopupButton addItemWithTitle:[anObject name]];

        int thisItem = [aPopupButton indexOfItemWithTitle:[anObject name]];

        [[aPopupButton itemAtIndex:thisItem] setTag:[[anObject uid] intValue]];
    }
}

显然,这取决于传递的任何对象数组是否符合name描述性字段的 a 和uid唯一标识符的 a。

任务完成。:-)

4

1 回答 1

2

并不是说这是最好的解决方案,但这是一个想法(您可能需要对其进行调整)。

添加一个带有标题的菜单项:

- (void)insertItemWithTitle:(NSString *)title atIndex:(NSInteger)index

所以,像这样:

[popupButton inserItemWithTitle:@"No selection" atIndex:0];

将它放在索引 0 将它放在顶部。如果您希望它位于列表的底部,请使用以下方法:

- (void)addItemWithTitle:(NSString *)title

然后,当您获得操作事件时,您可以检查索引 0 处的项目。如果它位于索引 0,您就知道它是“无选择”。

-(IBAction)popupSelectionAction:(id)sender {
     if (sender == popupButton) {
          //Check for "No selection"
          if ([popupButton indexOfSelectedItem] != 0) {
               //Update core data managed object value
          }
     }
}

或者,如果您使用 addItemWithTitle,请检查它是否是项目数组中的最后一项。

-(IBAction)popupSelectionAction:(id)sender {
     if (sender == popupButton) {
          //Check for "No selection"
          if ([popupButton indexOfSelectedItem] != ([popupButton numberOfItems]-1)) {
               //Update core data managed object value
          }
     }
}

类参考:

http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSPopUpButton_Class/Reference/Reference.html

于 2011-04-07T21:24:19.710 回答