3

I trying to add selector to my UISegmentedControl.

    segmentedControl = UISegmentedControl(items: items)
    segmentedControl.layer.cornerRadius = 12.0
    segmentedControl.layer.borderColor = UIColor.purpleLight.cgColor
    segmentedControl.layer.borderWidth = 1.0
    segmentedControl.layer.masksToBounds = true
    segmentedControl.backgroundColor = .white
    self.contentView.addSubview(segmentedControl)

    segmentedControl.addTarget(self, action: Selector(("changeColor:")), for:.valueChanged)

Then:

func changeColor(sender: UISegmentedControl) {
        switch sender.selectedSegmentIndex {
        case 1:
            segmentedControl.backgroundColor = UIColor.green
        case 2:
            segmentedControl.backgroundColor = UIColor.blue
        default:
            segmentedControl.backgroundColor = UIColor.purple
        }
    }

However, when i tap it, i got an error - unrecognized selector sent to instance 0x7fcf5f049000

Evgeniy Kleban
  • 6,794
  • 13
  • 54
  • 107
  • 3
    `#selector(changeColor(sender:))`? https://stackoverflow.com/questions/38038418/selector-in-swift3 – Larme Jul 25 '17 at 09:58
  • @Larme yes it work. But why syntax i wrote not work? – Evgeniy Kleban Jul 25 '17 at 09:59
  • @EvgeniyKleban There is a parameter argument with your function, which you've not passed with target selector. This is Swift 2 Selector syntax, which is changed in Swift 3. – Krunal Jul 25 '17 at 10:06

2 Answers2

5

Replace your action argument - selector. Since Swift 3, selector syntax has been changed.

segmentedControl.addTarget(self, action: #selector(self.changeColor(sender:)), for:.valueChanged)
Krunal
  • 77,632
  • 48
  • 245
  • 261
5

Krunal answer is correct and would fix your error, but to understand why it was done, you can read this:

The use of string literals for selector names is extremely error-prone: there is no checking that the string is even a well-formed selector, much less that it refers to any known method, or a method of the intended class. Moreover, with the effort to perform automatic renaming of Objective-C APIs, the link between Swift name and Objective-C selector is non-obvious. By providing explicit "create a selector" syntax based on the Swift name of a method, we eliminate the need for developers to reason about the actual Objective-C selectors being used.

Although, if you want to use Selector syntax and there may be cases where you want to call method by dynamic string names, you can still use Selector syntax. For methods in classes, that is subclass of NSObject, you can directly use Selector with string literal to call methods. The only condition is that you need to pass Objective-C method syntax inside Selector.

In your case, this will work:

segmentedControl.addTarget(self, action: Selector(("changeColorWithSender:")), for:.valueChanged)
Puneet Sharma
  • 9,369
  • 1
  • 27
  • 33