Search code examples
iosswiftgrand-central-dispatchwatchkit

Swift - alternative to dispatch_after


Swift/SO newbie here - will try to be clear!

I have an @IBAction being called from a wkinterfacepicker. This calls a function which may make a change to the picker again - which in turn causes the @IBAction to be triggered again, and so can result in unwanted loop-type behaviour.

What I am trying to do is to have control pass to the second func, rather than be called from/return to the @IBAction function. I have a working solution using dispatch_after, implementing an arbitrary delay so that the @IBAction finishes before the second func starts, but this does not seem very elegant/appropriate.

Here is roughly what that looks like:

@IBAction func freePickerChanged(value: Int) {
    selectedValue = value

    let triggerTime = (Int64(NSEC_PER_SEC) * 1)
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, triggerTime), dispatch_get_main_queue(), { () -> Void in
            self.changeValues()
    })
    // Without using dispatch_after, program control returns here from changeValues(), causing loop
}

//Ideally would call changeValues() here, after @IBAction exits

func changeValues() {
    //Do some calculations here. Perhaps the picker needs to be changed again using setSelectedItemIndex -  @IBACTION KICKED OFF AGAIN
}

Is there a better way to pass control to the second function from the @IBAction func as it exits? Or maybe I am just on the wrong track completely?

Thanks in advance for taking the time to look at this!


Solution

  • Rather than pick a random delay after which to run your code, another way to do this is to just put your block of code on to the main queue asynchronously. This will run after the current run loop completes so you don't have to work out how long to wait for.

    i.e instead of

    dispatch_after(...
    

    try

    dispatch_async(dispatch_get_main_queue()) {
        // your code here
    }