Swift - Pass inout parameter to scheduledTimer

144 views Asked by At

Is there a way to pass an inout parameter through a scheduledTimer method? I want a specific value(disable Button until timer has run out).

func Timer(Hz:TimeInterval, Activate: inout Bool, time:Double=10){
    let info = ProcessInfo.processInfo
    let begin = info.systemUptime
    var A=0
    // do something
    var diff = (info.systemUptime - begin)
    print("Time runs\n")
    let timer=Timer.scheduledTimer(withTimeInterval: Hz, repeats: true) { timer in
        diff=(info.systemUptime - begin)
        if (diff>=time){
            timer.invalidate()
            print("Finished")
            Activate = !Activate
            A=1
        }
    }
    if (A==1){
        print("Will never happen")
    }

    
}

Var A is just there to show that I also tried a different approach but it didn't work

2

There are 2 answers

0
Chip Jarred On

If the button is a reference type (ie, a class), which it will be if it's a UIKit or AppKit type, you can just pass it in, but there's a more general way of doing that is maybe better. Pass a closure in to act as a completion handler:

func Timer(Hz:TimeInterval, time:Double=10, onCompletion handler: @escaping () -> Void){
    let info = ProcessInfo.processInfo
    let begin = info.systemUptime
    var A=0
    // do something
    var diff = (info.systemUptime - begin)
    print("Time runs\n")
    let timer=Timer.scheduledTimer(withTimeInterval: Hz, repeats: true) { timer in
        diff=(info.systemUptime - begin)
        if (diff>=time){
            timer.invalidate()
            print("Finished")
            A=1
            handler() // <- Call completion handler here
        }
    }
    if (A==1){
        print("Will never happen")
    }
}

Then you can disable the button like this:

Timer(Hz: hz, time: time) { myButton.isEnabled = false /* or whatever else you want to do */ }
0
matt On

Your code seems unnecessarily complicated (though perhaps I have not understood the goal). Let's say we want to disable our button for 10 seconds, and then it should be enabled again. Then we would just say

    self.myButton.isEnabled = false
    self.toggleEnabled(self.myButton, after:10)

where toggleEnabled looks like this:

func toggleEnabled(_ enabled:UIButton, after t:Double) {
    Timer.scheduledTimer(withTimeInterval: t, repeats: false) { _ in
        enabled.isEnabled.toggle()
    }
}

If you really wanted to, you could use a protocol to hide from toggleEnabled the fact that this is a UIButton. But that's hardly needed just to do something so simple.