Sort NSPopUpButton

I have a list of items that should be displayed in NSPopUpButton. I want the PopUp button to display the list in alphabetical order. In addition, the list contains NEW MenuItem, which will extract a line from a text field and insert it into the PopUp button. So there are two questions I would like to ask:

  • What is the correct way to display a list of items in sorted order in NSPopUpButton?
  • How do I handle inserting a new item into NSPopUpButton to maintain sort order?
+4
source share
3 answers

I managed to sort the popup using the following bindings:

[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]; 

I also changed the instruction in init:

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

to

 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]; 

and sorting works fine.
Now the problem is that if I add a submenu to any of the menu items, and then add a new NSMenuItem to the array controller, the Sub-Menu previously added will disappear, as shown in the images below:

Before adding a new item:
enter image description here


After adding a new item:
enter image description here


The same behavior is displayed when sorting items.
Any ideas on how to fix this?

+1
source

If you use the NSArrayController button to populate the pop-up button (or rather its menu), then you can simply define a sort handle to handle the sort.

Getting the array controller to work with the pop-up button for the first time can be a bit complicated, but if you bind the contents of the pop-up button to the arrangedObjects array controller, and then bind the content values ​​to the appropriate string property of your model objects, you should be fine.

Then adding a new element will be just a matter of adding an element through an array controller.

So, in case you are not familiar with the NSArrayController class and binding, the following is a brief description of how you can do this in Interface Builder. Suppose your items have a string property called name .

  • Create a property (mutable) in your nib file owner (e.g. application delegate) to hold your items.
  • Create an array controller object in Interface Builder.
  • Bind your content array to the newly created array. Binding can be set in the Xcode Bindings Inspector (Cmd-Opt-7).
  • Add a popup to the window.
  • Set the content of the pop-up button button to the controller of the controller of the arrangedObjects controller. This is the default option for this binding.
  • Set the value of the contents of the contents of the pop-up button for the controller controller arrangedObjects and This will give the correct text in the menu.
  • Somewhere in your code, create a sort handle and set it on the array controller (using the setSortDescriptors: method). To do this, you may need to determine the output for the file owner to store the array controller.
  • To add a new item to your popup button, use the add: array controller method.

This should bring you to a minimum of your own code and a little magic in the Builder interface.

For fairly simple user interface elements, bindings can really save a lot of work. Read more about them here .

Edited to add an example:

For an example of how this can be done, consider an application with an application delegate that has a data property, an array of dictionaries, with a name property. Note that this is one level of abstraction deeper than your example, in which the array contains only single lines. Personally, I prefer that.

 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]; 
+2
source

Thanks for the answer @Monolo

I managed to load the values ​​(which were saved in NSMutableArray) in a popup from NSArrayController. But I still stick with sorting. Below is the code, I can not understand what is wrong with it. ControllerClass.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 
0
source

All Articles