A_toaster
A_toaster

Reputation: 1288

How can I call a function after a time delay in the main thread in Swift 3?

I have a UIControl that calls a function after 0.5 seconds depending on how many times the user presses it. (Eg 1 press calls f1(), 2 presses calls f2(), 3 presses calls f3())

So basically I need to set a timer when a user presses the Control. If the Control is not pressed for 0.5 seconds then create a dialog. I have tried using a DispatchQueue, but when it gets to the point of making the dialog, it takes several seconds. I think it is because it is being called concurrently instead of on the main thread (apologies if poor terminology).

self.operationQueue.cancelAllOperations() //To cancel previous queues
self.mainAsyncQueue = DispatchQueue(label: "bubblePressed" + String(describing: DispatchTime.now()), qos: DispatchQoS.default, attributes: DispatchQueue.Attributes.concurrent)

let time = DispatchTime.now()
self.currentTime = time

self.mainAsyncQueue!.asyncAfter(deadline: time + 0.5){
  guard self.currentTime == time else {
    return
  }

  let tempOperation = BlockOperation(block:{
    self.displayDialog()
  })
  self.operationQueue.addOperation(tempOperation)
}

operationQueue and mainAsycQueue are defined in viewDidLoad as

self.currentTime = DispatchTime.now()
self.operationQueue = OperationQueue()

How can I call my function displayDialog() in the main thread so that it loads faster?

Upvotes: 2

Views: 9685

Answers (3)

Paulw11
Paulw11

Reputation: 114836

I don't think it needs to be anywhere near that complicated. You can just use a Timer;

class MyClass: UIViewController {

    var tapCount = 0
    var tapTimer: Timer?

    @IBAction tapped(_ sender: Any) {
        if tapCount < 3 {
            tapCount += 1
            tapTimer?.invalidate()
            tapTimer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false, block: { (timer) in
                switch (self.tapCount) {
                    case 1:
                      self.f1()
                    case 2:
                      self.f2()
                    case 3:
                      self.f3()
                    default:
                      // Hmm, shouldn't happen
                }
                self.tapCount = 0
            })
    }
}

The timer will be scheduled on the main queue by default, so there is no need to dispatch anything on the main queue specifically

Upvotes: 3

adev
adev

Reputation: 2092

Based on the question title, answer is:

let deadlineTime = DispatchTime.now() + .seconds(1)
DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
   //update UI here
   self.displayDialog()
}

or

DispatchQueue.main.asyncAfter(deadline: .now() + 1) { 
   self.displayDialog()
}

Upvotes: 5

dahiya_boy
dahiya_boy

Reputation: 9503

Use below func, it executes the func in the main thread and no other action will perform during this execution.

DispatchQueue.main.async {
   self.displayDialog()                
}

Upvotes: 0

Related Questions