4

我有一个需要在 NSPopUpButton 中显示的元素列表。我希望 PopUp 按钮按字母顺序显示列表。此外,列表中有一个 NEW MenuItem,它将从文本字段中提取一个字符串并将其插入到 PopUp 按钮中。所以,有两个问题我想问:

  1. 在 NSPopUpButton 中按排序顺序显示元素列表的正确方法是什么?
  2. 我应该如何处理向 NSPopUpButton 插入新元素以保持排序顺序?
4

3 回答 3

2

如果您使用 anNSArrayController来填充弹出按钮(或者更确切地说,它的菜单),那么您可以定义一个排序描述符来处理排序。

第一次让数组控制器与弹出按钮一起工作可能有点棘手,但如果您将弹出按钮的内容绑定到数组控制器的内容arrangedObjects,然后将内容值绑定到模型对象的合适字符串属性,您应该美好的。

然后,添加一个新项目只需通过数组控制器添加一个项目。

因此,如果您不熟悉NSArrayController类和绑定,以下是如何在 Interface Builder 中进行的简短描述。假设您的元素有一个名为name.

  1. 在您的 nib 文件的所有者(例如,应用程序委托)中创建一个(可变的)数组属性来保存您的元素。
  2. 在 Interface Builder 中创建一个数组控制器对象。
  3. 将其内容数组绑定到您刚刚创建的数组属性。可以在 Xcode 的 Bindings Inspector (Cmd-Opt-7) 中设置绑定。
  4. 在窗口中添加一个弹出按钮。
  5. 将弹出按钮的内容绑定设置为数组控制器的arrangedObjects控制器键。这是该绑定的默认选项。
  6. 将弹出按钮的内容值绑定设置为数组控制器的arrangedObjects控制器键和name模型键路径。这将在菜单中提供正确的文本。
  7. 在您的代码中的某处,创建一个排序描述符并将其设置在数组控制器上(使用setSortDescriptors:方法)。为此,您可能希望在文件所有者上定义一个出口来保存阵列控制器。
  8. 要向弹出按钮添加新元素,请使用数组控制器的add:方法。

这应该让您使用最少的自己的代码,以及一点 Interface Builder 的魔力。

对于相当简单的 UI 元素,绑定确实可以节省很多工作。更多关于他们在这里

编辑添加一个例子:

有关如何完成此操作的示例,请考虑具有应用程序委托的应用程序,该应用程序具有data属性、字典数组和name属性。请注意,这是比您的示例更深的抽象级别,其中数组仅包含单个字符串。就个人而言,我更喜欢这种方式。

self.data = [NSMutableArray arrayWithObjects:
             [NSDictionary dictionaryWithObjectsAndKeys:@"Flowers", @"name", nil],
             [NSDictionary dictionaryWithObjectsAndKeys:@"Animals", @"name", nil],
             [NSDictionary dictionaryWithObjectsAndKeys:@"Trees", @"name", nil],
             nil];

// Sort the array controller alphabetically by the name property
NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];

self.arrayController.sortDescriptors = [NSArray arrayWithObject:sd];
于 2012-06-19T10:28:33.067 回答
1

我已经设法使用以下绑定对弹出按钮进行排序:

[arrayController bind:@"contentArray" toObject:self withKeyPath:@"displayElements" options:nil];
[popUpButton bind:@"content" toObject:arrayController withKeyPath:@"arrangedObjects" options:nil];
[popUpButton bind:@"contentValues" toObject:arrayController withKeyPath:@"arrangedObjects.title" options:nil];

我还更改了 init 中的语句:

displayElements = [[NSMutableArray alloc] initWithObjects:@"one",@"two",@"three", nil];

displayElements = [[NSMutableArray alloc] initWithObjects:[[NSMenuItem alloc]initWithTitle:@"one" action:nil keyEquivalent:@""],
                                                              [[NSMenuItem alloc]initWithTitle:@"two" action:nil keyEquivalent:@""],
                                                              [[NSMenuItem alloc]initWithTitle:@"three" action:nil keyEquivalent:@""],
                                                              nil];

并且排序工作得很好。
现在的问题是,如果我将子菜单添加到任何菜单项,然后我将新的 NSMenuItem 添加到数组控制器,则先前添加的子菜单会消失,如下图所示:

添加新项之前:
在此处输入图像描述


添加新项目后:
在此处输入图像描述


当我们对元素进行排序时,会显示相同的行为。
有关解决此问题的任何想法?

于 2012-06-22T12:11:26.070 回答
0

感谢@Monolo 的回答

我已经能够在 NSArrayController 的弹出窗口中加载值(已存储在 NSMutableArray 中)。但我仍然坚持排序的事情。下面是代码,我无法弄清楚它有什么问题。
控制器类.h

@interface ControllerClass : NSObject{
NSWindow *window;
NSArray *sortDescriptorArray;
NSMutableArray *displayElements;
NSSortDescriptor *sortDescriptor; 
IBOutlet NSArrayController *arrayController;
IBOutlet NSTextField *newItemTextField;
}
@property (readwrite,retain) NSMutableArray *displayElements;
-(id)init;
-(IBAction)AddItem:(id)sender;
@end

==================================================== ==========
ControllerClass.m

#import "ControllerClass.h"

@implementation ControllerClass
@synthesize displayElements;
-(id)init
{
    self =[super init];
    sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"displayElements" ascending:YES];
    sortDescriptorArray = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
    [arrayController setSortDescriptors:sortDescriptorArray];
    displayElements = [[NSMutableArray alloc] initWithObjects:@"one",@"two",@"three", nil];
    return self;
}

-(IBAction)AddItem:(id)sender
{
    [arrayController addObject:[newItemTextField stringValue]];
}
@end
于 2012-06-20T13:24:24.653 回答