Search code examples
swiftselectorunrecognized-selector

"unrecognized selector sent to instance" error in swift


I am creating a Stopwatch and so I created a button and added a action to start the stopwatch, but as soon as it invoked, I got this error:

2020-05-13 19:46:02.543555+1000 Timer Pro[27206:2613795] -[Timer_Pro.Stopwatch2ViewController updateStopwatch]: unrecognized selector sent to instance 0x7fb4d7425390

(lldb) 

What I am doing is having minutes, seconds and fractions in my stopwatch, and it starts from 0. Where every 0.01 seconds the fractions goes up, and at 99 it adds one to the seconds and resets the fractions, and when the seconds hit 59 it resets and adds one to the minutes. I have a lap table where when the lap button is pressed it puts the time on the lap table. On my UI I have a start button which when pressed turns into a stop button, and next to the stop/start button I have a lap button which when pressed turns into a reset button. I have 4 buttons in a file named stop.png, start.png, reset.png and lap.png. Here is my code:

import UIKit

class Stopwatch2ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {


    var timer = Timer()
    var minutes: Int = 0
    var seconds: Int = 0
    var fractions: Int = 0

    var stopWatchString: String = ""

    var startStopWatch: Bool = true
    var addLap: Bool = false

    @IBOutlet weak var stopwatchLabel: UILabel!

    @IBOutlet weak var lapsTableView: UITableView!

    @IBOutlet weak var startstopButton: UIButton!
    @IBOutlet weak var lapresetButton: UIButton! 

    @IBAction func startStop(_ sender: Any) {

        if startStopWatch == true {

            timer = Timer.scheduledTimer(timeInterval: 0.01, target: self, selector: Selector(("updateStopwatch")), userInfo: nil, repeats: true)
            startStopWatch = false

            startstopButton.setImage(UIImage(named: "stop.pnng"), for: UIControl.State.normal)
            lapresetButton.setImage(UIImage(named: "lap.png"), for: UIControl.State.normal)

            addLap = true

        }else {

            timer.invalidate()
            startStopWatch = true

            startstopButton.setImage(UIImage(named: "start.png"), for: .normal)
            lapresetButton.setImage(UIImage(named: "reset.png"), for: .normal)

            addLap = false

        }


    }

    @IBAction func lapReset(_ sender: Any) {

    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        stopwatchLabel.text = "00:00.00"
    }

    func updateStopWatch() {

        fractions += 1
        if fractions == 100 {

            seconds += 1
            fractions = 0
        }

        if seconds == 60 {

            minutes += 1
            seconds = 0
        }

        let fractionsString = fractions > 9 ? "\(fractions)" : "0\(fractions)"
        let secondsString = seconds > 9 ? "\(seconds)" : "0\(seconds)"
        let minutesString = minutes > 9 ? "\(minutes)" : "0\(minutes)"

        stopWatchString = "\(minutesString):\(secondsString).\(fractionsString)"
        stopwatchLabel.text = stopWatchString

    }



    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = UITableViewCell(style: UITableViewCell.CellStyle.value1, reuseIdentifier: "Cell")

        cell.backgroundColor = self.view.backgroundColor

        cell.textLabel?.text = "Lap"
        cell.detailTextLabel?.text = "00:00:00"


        return cell
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return 3
    }

}

It would be much appreciated if anyone is able to help me, as I am a beginner and this error has kept me up late at night for months.


Solution

  • You're creating Selector("updateStopwatch") but your method is called func updateStopWatch().

    Use #selector(self.updateStopWatch) instead, this only lets you create selectors on methods that actually exist.

    Also make sure that methods referred to by selectors must be visible to the Objective-C runtime, so you need to mark them as @objc.