1

I've implemented the comboBoxWillPopUp delegate method, but it is never called when I open the NSComboBox's popup.

Other delegate methods, such as comboBoxSelectionDidChange, implemented in the same class, are called as expected, so the comboBox seems to have been set up appropriately.

I tried deleting the project's derived data to ensure that the newly implemented method gets compiled, but this made no difference. If I set a breakpoint in the first line of the method, it is never hit.

I've missed obvious things in the past and suspect that's the case now. Any idea what it is?


Per uchuugaka's request, some code:

The comboBox is an outlet:

@property (nonatomic, retain) IBOutlet NSComboBox *cmbSubject;

Its controller formally implements the NSComboBoxDelegate protocol (among others):

@interface EditorController : NSWindowController <NSComboBoxDelegate, NSComboBoxDataSource, NSTextViewDelegate, NSTextStorageDelegate, NSTabViewDelegate, NSDrawerDelegate, NSTableViewDelegate, NSTableViewDataSource, NSWindowDelegate >

The comboBox delegate is assigned in the controller's awakeFromNib:

- (void) awakeFromNib {

// other stuff...

[self.cmbSubject setUsesDataSource:YES]; 
[self.cmbSubject setDataSource:self];
[self.cmbSubject setDelegate:self]; // controller (self) assigned as delegate
[self.cmbSubject setCompletes:YES]; 
// Tell the combobox to reload; otherwise it looks OK but thinks it's empty. 
// (Data source caches are in DataSourceCoordinator, which should be set up before this controller.)
[self.cmbSubject reloadData];

// other stuff...

}

The controller implements comboBoxWillPopUp:

- (void) comboBoxWillPopUp:(NSNotification *)notification {

// If breakpoint is added here, it is never hit.
NSComboBox *cmb = [notification object];

// Determine the maximum height available to the cmb popup...
CGFloat heightAvailable;
CGFloat heightScreen = [NSScreen mainScreen].frame.size.height;
CGFloat heightOriginCMB = cmb.frame.origin.y + self.window.frame.origin.y; // origin is from bottom
// ...which usually will be the space below the cmb...
if (heightOriginCMB >= heightScreen/2)
    heightAvailable = heightOriginCMB;
// ...unless user has positioned the window very low, in which case the cmb will present the popup on top if necessary.
else
    heightAvailable = heightScreen - heightOriginCMB;

// Determine the maximum number of items that can be displayed.
NSInteger iMaxItemsToDisplay = heightAvailable / [cmb itemHeight]; // truncate to whole number

// Ensure the max is at least 3, just in case.
// (If window contents are rearranged so that cmb origin is no longer relative to Editor window, or if item height is set to some large number, this could be an issue.)
if (iMaxItemsToDisplay < 3)
    iMaxItemsToDisplay = 3;

// Set cmb's numberOfVisibleItems, which acts as a maximum.
[cmb setNumberOfVisibleItems:iMaxItemsToDisplay];

}
Wienke
  • 3,723
  • 27
  • 40
  • Can you post some code? – uchuugaka May 17 '13 at 16:53
  • OK. I added code to the question. – Wienke May 17 '13 at 17:36
  • 1
    What happens if you add self as an observer of the notification that NSComboBox sends for willPopUp and set a selector to it? – uchuugaka May 17 '13 at 23:21
  • You can also use caveman debugging in the method with NSLog with an arg of NSStringFromSelector(_cmd) to log the method name if the method fires. (Sometimes easier than breakpoints) – uchuugaka May 17 '13 at 23:23
  • I tried adding `[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(comboBoxWillPopUp:) name:NSComboBoxWillPopUpNotification object:self.cmbSubject];` to awakeFromNib. The method is still not called. – Wienke May 18 '13 at 00:40
  • You suggestion gave me the idea of declaring a unique method and registering for *it* to be called: `[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(comboBoxWillPopUpAltMethod:) name:NSComboBoxWillPopUpNotification object:self.cmbSubject];` This *does* work. I'm not crazy about it as a workaround, though, because this controller has multiple comboboxes, all of which must be registered, and I'm essentially asking for *two* things to happen when a popup is invoked. – Wienke May 18 '13 at 01:14
  • Yeah I was afraid the docs were not clear there. It looks like the notification gets sent. Just observe which distinct instance sends the notification. That's not an unusual pattern. U could even move it from the app delegate to a specialized controller. – uchuugaka May 18 '13 at 02:11
  • Thanks for you help, uchuugaka. I'm using the workaround for now, but am leaving the question open because I do not understand why the delegate setup is working for everything but willPopUp. – Wienke May 18 '13 at 16:01

0 Answers0