3

I'm trying to implement a system that changes a label based on the state of an NSPopUpButton.
So far I've tried to do what's displayed in the code below, but whenever I run it, the code just jumps into the else clause, throwing an alert

- (IBAction)itemChanged:(id)sender {
    if([typePopUp.stringValue isEqualToString: @"Price per character"]) {
        _currency = [currencyField stringValue];
        [additionalLabel setStringValue: _currency];

    }
    else if([typePopUp.stringValue isEqualToString: @"Percent saved"]) {
        _currency = additionalLabel.stringValue = @"%";
    }

    else alert(@"Error", @"Please select a calculation type!");
}

So does anyone here know what to do to fix this?

Electric Coffee
  • 11,733
  • 9
  • 70
  • 131
  • First, what is "typePopup" ? If it is the NSPopUpButton itself, then your on the wrong object. you should use the popup's selection instead (typePopUp.selectedItem.xxxxx). – Motti Shneor Apr 11 '16 at 04:30

2 Answers2

5

@hamstergene is on the right track, but is comparing the title of the menu item rather than, say, the tag, which is wrong for the following reasons:

  1. It means you cannot internationalize the app.
  2. It introduces the possibility of spelling mistakes.
  3. It's an inefficient comparison; comparing every character in a string takes way longer than comparing a single integer value.

Having said all that, NSPopUpButton makes it difficult to insert tags into the menu items, so you need to use the index of the selected item:

Assume you create the menu items using:

[typePopUp removeAllItems];
[typePopUp addItemsWithTitles: [NSArray arrayWithObjects: @"Choose one...", @"Price per character", @"Percent saved", nil]];

Then create an enum that matches the order of the titles in the array:

typedef enum {
    ItemChooseOne,
    ItemPricePerCharacter,
    ItemPercentSaved
} ItemIndexes;

And then compare the selected item index, as follows:

- (IBAction)itemChanged:(id)sender {
    NSInteger index = [(NSPopUpButton *)sender indexOfSelectedItem];
    switch (index) {
    case ItemChooseOne:
        // something here
        break;
    case ItemPricePerCharacter:
        _currency = [currencyField stringValue];
        [additionalLabel setStringValue: _currency];
        break;
    case ItemPercentSaved:
        _currency = @"%";               // See NOTE, below
        additionalLabel.stringValue = @"%";
        break;
    default:
        alert(@"Error", @"Please select a calculation type!");
    }
}

NOTE the following line was incorrect in your code:

_currency = additionalLabel.stringValue = @"%";

Multiple assignment works because the result of x = y is y. This is not the case when a setter is involved. The corrected code is above.

EDIT This answer was heavily edited following more info from the OP.

trojanfoe
  • 120,358
  • 21
  • 212
  • 242
2

To query the title of currently selected item in NSPopUpButton:

NSMenuItem* selectedItem = [typePopUp selectedItem];
NSString* selectedItemTitle = [selectedItem title];

if ([selectedItemTitle isEqualTo: ... ]) { ... }

Note that comparing UI strings is a very bad idea. A slightest change in UI will immediately break your code, and you are preventing future localization. You should assign numeric or object values to each item using -[NSMenuItem setTag:] or -[NSMenuItem setRepresentedObject:] and use them to identify items instead.

hamstergene
  • 24,039
  • 5
  • 57
  • 72