Search code examples
iosswiftnstimer

Pass a Swift function to NSTimer


I have some function inside another function. in function1 i want to use NSTimer to call func2 after some time like this:

func myFunc1()
{
   NSTimer.scheduledTimerWithTimeInterval(1, target: ??, selector:#selector(myFunc2()), userInfo: nil, repeats: false)
   func myFunc2()
   {
      // do something...
   }
}

What is the right "target" value that i should pass there? is it even possible?


Solution

  • If you are targeting pre-iOS 10, you can't pass a function to NSTimer because no API was introduced at that time to support closure callbacks.

    iOS 10 and later Approach

    // swift 2.x users should still use NSTimer instead
    Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true) { timer in
        // ...
    }
    

    Generic Approach

    You can add this class, and reuse it anytime:

    final class TimerInvocation: NSObject {
    
        var callback: () -> ()
    
        init(callback: @escaping () -> ()) {
            self.callback = callback
        }
    
        func invoke() {
            callback()
        }
    }
    
    extension Timer {
    
        static func scheduleTimer(timeInterval: TimeInterval, repeats: Bool, invocation: TimerInvocation) {
    
            Timer.scheduledTimer(
                timeInterval: timeInterval,
                target: invocation,
                selector: #selector(TimerInvocation.invoke(timer:)),
                userInfo: nil,
                repeats: repeats)
        }
    }
    

    With this class, you can simply do this now:

    let invocation = TimerInvocation {
        /* invocation code here */
    }
    
    NSTimer.scheduledTimerWithTimeInterval(1, target: invocation, selector:#selector(TimerInvocation.invoke), userInfo: nil, repeats: false)
    

    You don't have to worry about retaining the invocation variable since it is retained by NSTimer