Value of type '(UISwitch) -> ()' has no member "isOn" error

Hey


I was just wondering why I am getting this error when I'm doing what the "Intro to App Development with Swift" book. My error is on lesson 17.3 and here is my code: (just wondering what I'm doing wrong, I'm new to Swift!!)



import UIKit

class ViewController: UIViewController {

override func viewDidLoad() {

super.viewDidLoad()

updateColor()

/

}

override func didReceiveMemoryWarning() {

super.didReceiveMemoryWarning()

/

}

@IBOutlet weak var colorView: UIView!


@IBAction func redSwitch(_ sender: UISwitch) {

}


@IBAction func greenSwitch(_ sender: UISwitch) {

}

@IBAction func blueSwitch(_ sender: UISwitch) {

}

func updateColor() {

var red: CGFloat = 0

var green: CGFloat = 0

var blue: CGFloat = 0

if redSwitch.isOn { error here

red = 1

}

if greenSwitch.isOn { error here

green = 1

}

if blueSwitch.isOn { error here

blue = 1

}

let color = UIColor(red: red, green: green, blue: blue, alpha: 1)

colorView.backgroundColor = color

}

}

Your functions redSwitch, greenSwitch and blueSwitch are methods called when a UISwitch element is toggled. So, they don't have a value. You have to arrange to keep track of the value. One way is like this (relevant code only):


    @IBOutlet var redSwitch: UISwitch!
    @IBOutlet var greenSwitch: UISwitch!
    @IBOutlet var blueSwitch: UISwitch!
    @IBAction func updateColor(_ sender: Any) {
        var red: CGFloat = 0
        var green: CGFloat = 0
        var blue: CGFloat = 0
        if redSwitch.isOn {
            red = 1
        }
        if greenSwitch.isOn {
            green = 1
        }
        if blueSwitch.isOn {
            blue = 1
        }
        let color = UIColor(red: red, green: green, blue: blue, alpha: 1)
        colorView.backgroundColor = color
    }


In addition, in Interface Builder you would need to connect the 3 outlets to the corresponding UISwitch controls, and use "updateColor" as the action method for all three UISwitch controls.


Or you can keep the existing action methods and do something like this (partial code only):


    var redSwitchIsOn = false
    @IBAction func redSwitch(_ sender: UISwitch) {
          redSwitchIsOn = sender.isOn
    }


and later:


        if redSwitchIsOn {
            red = 1
        }
Accepted Answer

Your mistake has been to create IBActions where the instructions said to create IBOutlets.


Your `redSwitch`, `greenSwitch` and `blueSwitch` identifiers each reference a closure with type '(UISwitch) -> ()`, which doesn't have a property named `isOn`, hence the errors.


`redSwitch`, `greenSwitch` and `blueSwitch` would each have referenced a UISwitch object, which does have an `isOn` property, if you had created IBOutlets as instructed by the exercise instead of IBActions.


My recommendation is that you redo that exercise from the very beginning because you have created IBActions where it tells you to create IBOutlets, and an IBAction you should have created is missing from your code. The code you posted can be amended to make something that works, but I think it's important that you learn how to correctly create actions and outlets by following the instructions more carefully.


Your final code should look similar to:


import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var colorView: UIView!

    @IBOutlet weak var redSwitch: UISwitch!
    @IBOutlet weak var greenSwitch: UISwitch!
    @IBOutlet weak var blueSwitch: UISwitch!

    @IBAction func switchChanged(_ sender: UISwitch) {
        updateColor()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        updateColor()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    func updateColor() {
        var red: CGFloat = 0
        var green: CGFloat = 0
        var blue: CGFloat = 0
        if redSwitch.isOn {
            red = 1
        }
        if greenSwitch.isOn {
            green = 1
        }
        if blueSwitch.isOn {
            blue = 1
        }
        let color = UIColor(red: red, green: green, blue: blue, alpha: 1)
        colorView.backgroundColor = color
    }
}

THANK YOU!!! I did create IBActions instead of IBOutlets. All works fine now. Thanks!!

Golddad,


I am having a similar situation and I have not been able to solve it. I did move forward in the lesson to create the sliders swithcs. The problem is in the in line 37 of the above:


  1. let color = UIColor(red: red, green: green, blue: blue, alpha: 1)
  2. colorView.backgroundColor = color
  3. }


in my case I have my code as follows:



import UIKit

class ViewController: UIViewController {

@IBOutlet weak var ColorView: UIView!

@IBOutlet weak var redSwitch: UISwitch!

@IBOutlet weak var greenSwitch: UISwitch!

@IBOutlet weak var blueSwitch: UISwitch!

@IBOutlet weak var redSlider: UISlider!

@IBOutlet weak var greenSlider: UISlider!

@IBOutlet weak var blueSlider: UISlider!

override func viewDidLoad() {

super.viewDidLoad()

/

updateColor()

}

override func didReceiveMemoryWarning() {

super.didReceiveMemoryWarning()

/

}

@IBAction func switchChanged(_ sender: UISwitch){

updateColor()

}

func updateColor() {

var red: CGFloat = 0

var green: CGFloat = 0

var blue: CGFloat = 0

if redSwitch.isOn {

red = CGFloat(redSlider.value)

}

if greenSwitch.isOn {

green = CGFloat(greenSlider.value)

}

if blueSwitch.isOn {

blue = CGFloat(blueSlider.value)

}

let color = UIColor(red: red, green, green, blue: blue, alpha: 1)

ColorView.backgroundColor = color

}


@IBAction func sliderChaged(_ sender: Any){

}

@IBAction func reset(_ sender: Any) {

}

}

What is the error message you get ?

Helo everyone, i have a problem and dont know what is the solutin. It's the same Lecture, i'm geting next eror message. This I don't know if it has something to do about the Swift 4 version.


let color = UIColor(red: red, green, green, blue: blue, alpha: 1) . Argument labels '(redd:, greenn:, bluee:)' do not match any available overloads

It's not about Swift 4. It's not clear exactly what's going on, because it's not clear if you retyped the code and error in your post and made a type, of this was your action code. This


UIColor(red: red, green, green, blue: blue, alpha: 1)


is mal-formed because there should be a ":" after the keyword "green", not a comma:


UIColor(red: red, green: green, blue: blue, alpha: 1)


Also, it's odd that the error message shows doubled letters (redd, greenn, bluee). If that's really what it says, and the doubled letters are really not in your source code, then it looks like an Xcode bug that has corrupted the source. (In that case, try deleting the line and re-typing it.)


Can you double-check what you really have in your source?

Thank you for leading me to my mistake. It was 2am in the country where i'm from and i overlook stupid type mistake.

Hi Goldsdad.


Now, I am TOTALLY lost!!! I had the same problem as the O.P. Which is why I found this thread.


Initially, we have one switch. To accomplish something when the switch is turned on, we connect to the code with an action. Totally makes sense, and it jives with the Xcode documentation which states, in part: Your object receives messages from a control if it is the target of an action defined by the control. For example, when the user clicks a button, the button sends an action message to a target. When you add an action connection, Interface Builder adds an action method to your class and sets the target for the control to an instance of your class.


Then, when we want to have three switches, we have to create outlets, not actions?!?!


Whoa! How come? Here's what the Xcode doc says about outlets: To enable your code to send messages to a user interface object, add a connection from the user interface object to a special property in your class called an outlet.


But I don't want to send messages TO the switches!!! I want the exact opposite: for the switches to send me a message (that they're ON or OFF)!!!


I can understand that I would need to use an outlet if I wanted to programmatically set the state of the switch. But this is not what we want to do in this app!


Can you explain, in simple terms, what is going on here and why we should use an action for one switch, but outlets for three switches?


Thanks!

IBOutlets let you get a reference to an object in storyboard.

For instance, if you want to access one of its properties (e.g., tag, title, state, …) or change one of its properties.

Or if you need to know which object has sent a message (see just after)


IBActions is used when you want the object to send a message on certain event (tap inside for instance).


Effectively, you do not usually need to have declared an IBOutlet for this.


So, if you have 3 switches, you can create 3 IBActions, one for each.

code may be like


var value1 = false
var value2 = false
var value3 = false     // 3 properties in the class

@IBAction switch1Action(_ sender: UISwitch) {
            value1 = sender.isOn
}
@IBAction switch2Action(_ sender: UISwitch) {
            value2 = sender.isOn
}

@IBAction switch3Action(_ sender: UISwitch) {
            value3 = sender.isOn
}

But, if the code in IBAction are very similar, you may want to have a common IBAction.

Now, you have to know which UISwitch has sent the message ; and you connect the 3 UISwitch to the SAME IBAction.


You will declare 3 IBOutlets:

@IBOutlet weak var switch1 : UISwitch!
@IBOutlet weak var switch2 : UISwitch!
@IBOutlet weak var switch3 : UISwitch!

@IBAction switchAction(_ sender: UISwitch) {
       if sender == switch1 {
            value1 = sender.isOn
          } else if sender == switch2 {
            value2 = sender.isOn
          } else if sender == switch3 {
            value3 = sender.isOn
          }
}


Of course this case is a bit trivial, but shows the mechanism.

Hi Claude. Thanks for the response.


To get things straight in my mind:


1- Is it OK to say that an "@IBOutlet..." statement is a link?

2- Is it OK to say that an "@IBOutlet..." statement is not a property, but it "gives access" to the properties of the object (to which it is linked)?

3- Is an "@IBAction..." a function?

3- Suppose I have a button that is supposed to do something when it is clicked. I would need to define an "@IBAction...", linked to that button. Now suppose that I want to change one of the button's properties when it is clicked: is this a case where I would also need to define an "@IBOutlet..."?


Thanks for your help!

I hope I will use the right wording


1- Is it OK to say that an "@IBOutlet..." statement is a link?

It is a link to the object and a var declaration

when you write:

@IBOutlet weak var label: UILabel!

you create a property: label

and @IBOutlet lets you connect to the object

you could simply write

var label: UILabel!

and create the object programmatically


2- Is it OK to say that an "@IBOutlet..." statement is not a property, but it "gives access" to the properties of the object (to which it is linked)?

@IBOutlet allows to create the link to the object

var label: UILabel! create the var


3- Is an "@IBAction..." a function?

It is the same principle:

When you write (sorry, in my previous post I omitted func !!!!):

@IBAction func switchAction(_ sender: UISwitch)

you create a func

func switchAction(_ sender: UISwitch)

In fact, you can call the func written in IBAction from your code, like any other function

and @IBAction lets you connect to the object sent message ; for a button, it is by default touch up inside, but you could connect to another event.


4- Suppose I have a button that is supposed to do something when it is clicked. I would need to define an "@IBAction...", linked to that button. Now suppose that I want to change one of the button's properties when it is clicked: is this a case where I would also need to define an "@IBOutlet..."?

You got it.

When you say "@IBAction...", linked to that button, you mean in fact linked to the message sent (as you can see in Connections inspector for the button).

All right!


Thank you very much for your answers!

To make it a bit more complex, on point 4:

4- Suppose I have a button that is supposed to do something when it is clicked. I would need to define an "@IBAction...", linked to that button. Now suppose that I want to change one of the button's properties when it is clicked: is this a case where I would also need to define an "@IBOutlet..."?

In fact, if you pass the object as a parameter, you can directly modify it, without needing IBOutlet:


    @IBAction func changeMyName(sender: UIButton) {
       
     print(sender.titleLabel!.text!)
     sender.setTitle("New title", for: .normal)
    }

OK. Thanks.

Value of type '(UISwitch) -> ()' has no member "isOn" error
 
 
Q