Search code examples
swiftswiftuitimer

Call function and pass parameter when Timer is done in Swift


I'm trying to save the value entered in a textField 2 seconds after the user stops typing. I found this example that uses .debounce from the Combine framework which works fine but for some reason, it feels like I overcomplicated things and I would rather use a simple timer.

The issue with the following code is that I cannot pass the value from the logInputValue(inputValue:) method to the doSomething() method when the timer is done. Right now it calls the doSomething() method but it doesn't pass any parameter.

How can I pass a string parameter from the logInputValue(inputValue:) method to the doSomething() method when the timer is done?

Service Model

class ServiceModel{
    var myTimer = Timer()
    
    func logInputValue(inputValue:String){
        if myTimer.isValid{
            myTimer.invalidate()
        }
        myTimer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(doSomething), userInfo: nil, repeats: false)
    }
    @objc func doSomething(){
        print("Timer is done")
        // save the value currenlty in the textField
    }
}

SwiftUI

TextField('enter number', text: $myTextField)
    .onChange(of: myTextField) { value in
        serivceModel.logInputValue(inputValue: value)
    }

I also tried using the timer as follows but couldn't make it work. It saves each character typed in the field not just what's in the field after the 2 seconds after the user stops typing.

func logInputValue(inputValue:String){
    self.timer = Timer.scheduledTimer(withTimeInterval: 2, repeats: false, block: { _ in
        if timer.isValid{
            timer.invalidate()
        }
        // save the value currenlty in the myTextField
    })
}

Solution

  • There's a version of Timer that runs with a closure instead of a selector:

    myTimer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false) { [weak self] _ in
        self?.doSomething(inputValue)
    }
    
    // ...
    
    func doSomething(_ value: String) {
      // ...
    } 
    

    https://developer.apple.com/documentation/foundation/timer/2091889-scheduledtimer