How to program a delay in Swift 3

2019-01-03 19:56发布

In earlier versions of Swift, one could create a delay with the following code:

let time = dispatch_time(dispatch_time_t(DISPATCH_TIME_NOW), 4 * Int64(NSEC_PER_SEC))
dispatch_after(time, dispatch_get_main_queue()) {
    //put your code which should be executed with a delay here
}

But now, in Swift 3, Xcode automatically changes 6 different things but then the following error appears: "Cannot convert DispatchTime.now to expected value dispatch_time_t aka UInt64."

How can one create a delay before running a sequence of code in Swift 3?

6条回答
The star\"
2楼-- · 2019-01-03 20:19

Try the following function implemented in Swift 3.0 and above

func delayWithSeconds(_ seconds: Double, completion: @escaping () -> ()) {
    DispatchQueue.main.asyncAfter(deadline: .now() + seconds) { 
        completion()
    }
}

Usage

delayWithSeconds(1) {
   //Do something
}
查看更多
爱情/是我丢掉的垃圾
3楼-- · 2019-01-03 20:19

//Runs function after x seconds

public static func runThisAfterDelay(seconds: Double, after: @escaping () -> Void) {
    runThisAfterDelay(seconds: seconds, queue: DispatchQueue.main, after: after)
}

public static func runThisAfterDelay(seconds: Double, queue: DispatchQueue, after: @escaping () -> Void) {
    let time = DispatchTime.now() + Double(Int64(seconds * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC)
    queue.asyncAfter(deadline: time, execute: after)
}

//Use:-

runThisAfterDelay(seconds: x){
  //write your code here
}
查看更多
劫难
4楼-- · 2019-01-03 20:19

I do it in Swift 4:

Thread.sleep(until: Date(timeIntervalSinceNow: 2.5))

This one line of code blocks the current thread until the specified time finished. Delay time is defined in Date format. The above used version of the Date initializer just take a value for second in Double format. This value could have millisecond resolution.

Note that if you call this code on the main thread the UI will freeze for the specified time.

查看更多
闹够了就滚
5楼-- · 2019-01-03 20:23

I like one-line notation for GCD, it's more elegant:

    DispatchQueue.main.asyncAfter(deadline: .now() + 42.0) {
        // do stuff 42 seconds later
    }

Also, in iOS 10 we have new Timer methods, e.g. block initializer:

(so delayed action may be cancelled)

    let timer = Timer.scheduledTimer(withTimeInterval: 42.0, repeats: false) { (timer) in
        // do stuff 42 seconds later
    }

Btw, keep in mind: by default, timer is added to the default run loop mode. It means timer may be frozen when this loop mode is on hold (for example, when scrolling a UIScrollView) You can solve this issue by adding the timer to the specific run loop mode:

RunLoop.current.add(timer, forMode: .commonModes)

At this blog post you can find more details.

查看更多
萌系小妹纸
6楼-- · 2019-01-03 20:35

Try the below code for delay

//MARK: First Way

func delayForWork() {
    delay(3.0) {
        print("delay for 3.0 second")
    }
}

delayForWork()

// MARK: Second Way

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    // your code here delayed by 0.5 seconds
}
查看更多
家丑人穷心不美
7楼-- · 2019-01-03 20:37

After a lot of research, I finally figured this one out.

DispatchQueue.main.asyncAfter(deadline: .now() + 2) { // change 2 to desired number of seconds
   // Your code with delay
}

This creates the desired "wait" effect in Swift 3 and Swift 4.

Inspired by a part of this answer.

查看更多
登录 后发表回答