Skeleton Bow
Skeleton Bow

Reputation: 529

Getting current NSPopUpButton's selection with titleOfSelectedItem returns "optional value"

Edit: I figured out how to prevent this, but I still have a question as to why it returns an optional value. You may skip to the end.

I'm quite new to Swift, and I'm getting behavior I can't understand. Let's say I drag a popup button called myButton into the ViewController. I want to print the currently selected item to the console. Here's how I would do it:

  @IBOutlet weak var myButton: NSPopUpButton!

  override func viewDidLoad() {
    super.viewDidLoad()

    let myVariable = myButton.titleOfSelectedItem
    print(myVariable)

    // Do any additional setup after loading the view.
  }

I expect Item1 to be printed, as that's the option selected by default when the view loads. However, I actually get Optional("Item 1").

This has been causing a few problems for me. For example, the print(myVariable) line gives me this cryptic error:

Expression explicitly coerced from 'String?' to Any

Also, I can't do something like this:

if myButton.titleOfSelectedItem == "Item1" || "Item3" {
  let currentSelection = "odd"
} else {
  let currentSelection = "even"
}

as I get a bunch of errors – because of the || and the else as far as I can tell, even though I think it should work fine.

I've tried searching for why this occurs, but couldn't find any explanations. From the warning, it seems like when I get the selection with titleOfSelectedItem, it gives me an optional value. This doesn't make sense, as a menu item has to be selected. Its value can't be nil.

I looked up a bunch of tutorials to see how they implement popup button functionality. The only thing I could see was when someone

  1. Made an array
  2. Removed all items from the popup button with func removeAllItems()
  3. Added items to the popup button from the array with func addItems(withTitles: [String])
  4. Obtained the index of the selected item with var indexOfSelectedItem: Int
  5. Retrieved the respective value from the array

and then used that. This, however, seems unnecessarily complicated and I can't understand why I wouldn't be able to get just the title of the selected popup item simply with myButton.titleOfSelectedItem. Can anyone suggest to me what to do?

Edit:

So I realized you need to "unwrap" the optional value to make it a normal value, which is as simple as adding a ! to the end of the variable, as follows:

  @IBOutlet weak var myButton: NSPopUpButton!

  override func viewDidLoad() {
    super.viewDidLoad()

    let myVariable = myButton.titleOfSelectedItem!
    print(myVariable)

    // Do any additional setup after loading the view.
  }

Now there's no error, and Item1 is printed.

What I can't yet understand is, why was an optional value printed in the first place? There are three items in the NSPopUpButton. Any one of the three has to be selected. There's no opportunity for myButton.titleOfSelectedButton to be nil. Why then do I need to unwrap it to use it as a string with myButton.titleOfSelectedButton! if it's not optional?

Upvotes: 0

Views: 1869

Answers (2)

Obeone
Obeone

Reputation: 1

In Objective C you can do it in awakeFromNib:

[[your_NSView your_NSPopUpButton] selectItemAtIndex:your_Int];

... of course, you must have declared 'your_NSView' and 'your_NSPopUpButton' as properties.

Upvotes: 0

vadian
vadian

Reputation: 285069

titleOfSelectedItem returns an optional because no item could be selected.

You need optional bindings to unwrap the optional safely and you have to evaluate both "Item1" and "Item3" against the title string:

if let title = myButton.titleOfSelectedItem {

    print(title)
    let currentSelection : String
    if title == "Item1" || title == "Item3" {
       currentSelection = "odd"
    } else {
       currentSelection = "even"
    }


}

Upvotes: 1

Related Questions