How do I connect a control to a method programmatically? - Develop In Swift Fundamentals - Programmatic Actions

I am learning to code with swift. I am reading the free book from Apple Education titled "Develop In Swift Fundamentals". I am on the chapter titled "Controls In Action" and the section of the chapter I'm stuck on is titled "Programmatic Actions" (page 287).

The section has me connect a UIButton programmatically by first manually typing in the @IBOutlet for the UIButton then connecting the button using this code below.

button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)

I pasted this code right after the viewDidLoad function, however I get 6 red errors. I don't know what I did wrong. How do I connect a control to a method programmatically?

I've attached a link to the Github repository if you want to download the code and run it in Xcode.
The github repository

import UIKit
class ViewController: UIViewController {
    @IBOutlet var toggle: UISwitch!
    @IBOutlet var slider: UISlider!
    @IBOutlet var button: UIButton!
    override func viewDidLoad() {
        super.viewDidLoad()
        button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
    }
    @IBAction func buttonTapped(_ sender: Any) {
        print("Button was tapped!")
        if toggle.isOn {
            print("The switch is on!")
        } else {
            print("The switch is off.")
        }
        print("The slider is set to \(slider.value).")
    }
    @IBAction func switchToggled(_ sender: UISwitch) {
        if sender.isOn {
            print("Switch is on!")
        } else {
            print("Switch is off!")
        }
    }
    @IBAction func sliderValueChanged(_ sender: UISlider) {
        print(sender.value)
    }
    @IBAction func keyboardReturnKeyTapped(_ sender: UITextField) {
        if let text = sender.text {
            print(text)
        }
    }
    @IBAction func textChanged(_ sender: UITextField) {
        if let text = sender.text {
            print(text)
        }
    }
    @IBAction func respondToTapGesture(_ sender: UITapGestureRecognizer) {
        let location = sender.location(in: view)
        print(location)
    }
}

In swift that kind of code has to be inside a function. Put it inside viewDidLoad(). The braces indicate the start/end of the function. { ... }

Code that goes outside of functions is variable declarations and initializations, like your @IBOutlet declarations.

BTW, the markdown for code in this forum is three backticks. ```

It builds now after moving the code into the viewDidLoad. But now I get a fatal error.

Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value

This error indicates that an implicitly unwrapped optional was accessed but its value was nil. Your IBOutlets are probably the only IUOs in your code.

Few suggestions:

Review the tutorial to be sure you've done all the steps it requires.

Debug the crash to find out the line of code that is causing the nil optional.
Set breakpoints in viewDidLoad() and the other functions and see what line crashes.

Most likely you haven't connected one or more of the IBOutlets.

1 Like