添加“未选定”选项以绑定NSPopupButton

时间:2011-04-07 17:39:25

标签: objective-c core-data cocoa-bindings nsmenuitem nspopupbutton

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

NSArray 'A' of core data entities --> Array Controller
Array Controller --> NSPopupButton.contentValues.arrangedObjects.name

NSArray 'B' of core data entities --> Array Controller
Array Controller --> NSPopupButton.selectedObject.methodOnObject.name

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

-(MyWidget *)selectedWidget {

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

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

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

    [self setWidgetID:[anObj uid]];
}

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

我可以使用“无选择占位符”处理此问题,但只要用户选择其中一个项目,就会从列表中删除未选中的占位符。

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

我考虑过将一个实体对象添加到核心数据存储中,该数据存储具有所有基于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和唯一标识符的uid

完成工作。 : - )

1 个答案:

答案 0 :(得分: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