dispatch_after - GCD in Swift?

前端 未结 25 2382
心在旅途
心在旅途 2020-11-21 06:07

I\'ve gone through the iBook from Apple, and couldn\'t find any definition of it:

Can someone explain the structure of dispatch_after?

d         


        
相关标签:
25条回答
  • 2020-11-21 06:46

    Another way is to extend Double like this:

    extension Double {
       var dispatchTime: dispatch_time_t {
           get {
               return dispatch_time(DISPATCH_TIME_NOW,Int64(self * Double(NSEC_PER_SEC)))
           }
       }
    }
    

    Then you can use it like this:

    dispatch_after(Double(2.0).dispatchTime, dispatch_get_main_queue(), { () -> Void in
                self.dismissViewControllerAnimated(true, completion: nil)
        })
    

    I like matt's delay function but just out of preference I'd rather limit passing closures around.

    0 讨论(0)
  • 2020-11-21 06:46

    In Swift 3.0

    Dispatch queues

      DispatchQueue(label: "test").async {
            //long running Background Task
            for obj in 0...1000 {
                print("async \(obj)")
            }
    
            // UI update in main queue
            DispatchQueue.main.async(execute: { 
                print("UI update on main queue")
            })
    
        }
    
        DispatchQueue(label: "m").sync {
            //long running Background Task
            for obj in 0...1000 {
                print("sync \(obj)")
            }
    
            // UI update in main queue
            DispatchQueue.main.sync(execute: {
                print("UI update on main queue")
            })
        }
    

    Dispatch after 5 seconds

        DispatchQueue.main.after(when: DispatchTime.now() + 5) {
            print("Dispatch after 5 sec")
        }
    
    0 讨论(0)
  • 2020-11-21 06:47

    matt's syntax is very nice and if you need to invalidate the block, you may want to use this :

    typealias dispatch_cancelable_closure = (cancel : Bool) -> Void
    
    func delay(time:NSTimeInterval, closure:()->Void) ->  dispatch_cancelable_closure? {
    
        func dispatch_later(clsr:()->Void) {
            dispatch_after(
                dispatch_time(
                    DISPATCH_TIME_NOW,
                    Int64(time * Double(NSEC_PER_SEC))
                ),
                dispatch_get_main_queue(), clsr)
        }
    
        var closure:dispatch_block_t? = closure
        var cancelableClosure:dispatch_cancelable_closure?
    
        let delayedClosure:dispatch_cancelable_closure = { cancel in
            if closure != nil {
                if (cancel == false) {
                    dispatch_async(dispatch_get_main_queue(), closure!);
                }
            }
            closure = nil
            cancelableClosure = nil
        }
    
        cancelableClosure = delayedClosure
    
        dispatch_later {
            if let delayedClosure = cancelableClosure {
                delayedClosure(cancel: false)
            }
        }
    
        return cancelableClosure;
    }
    
    func cancel_delay(closure:dispatch_cancelable_closure?) {
    
        if closure != nil {
            closure!(cancel: true)
        }
    }
    

    Use as follow

    let retVal = delay(2.0) {
        println("Later")
    }
    delay(1.0) {
        cancel_delay(retVal)
    }
    

    credits

    Link above seems to be down. Original Objc code from Github

    0 讨论(0)
  • 2020-11-21 06:47

    Although not the original question by the OP, certain NSTimer related questions have been marked as duplicates of this question, so it is worth including an NSTimer answer here.

    NSTimer vs dispatch_after

    • NSTimer is more high level while dispatch_after is more low level.
    • NSTimer is easier to cancel. Canceling dispatch_after requires writing more code.

    Delaying a task with NSTimer

    Create an NSTimer instance.

    var timer = NSTimer()
    

    Start the timer with the delay that you need.

    // invalidate the timer if there is any chance that it could have been called before
    timer.invalidate()
    // delay of 2 seconds
    timer = NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false) 
    

    Add a function to be called after the delay (using whatever name you used for the selector parameter above).

    func delayedAction() {
        print("Delayed action has now started."
    }
    

    Notes

    • If you need to cancel the action before it happens, simply call timer.invalidate().
    • For a repeated action use repeats: true.
    • If you have a one time event with no need to cancel then there is no need to create the timer instance variable. The following will suffice:

      NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false) 
      
    • See my fuller answer here.

    0 讨论(0)
  • 2020-11-21 06:48

    Simplest solution in Swift 3.0 & Swift 4.0 & Swift 5.0

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

    Usage

    delayWithSeconds(1) {
       //Do something
    }
    
    0 讨论(0)
  • 2020-11-21 06:51

    Now more than syntactic sugar for asynchronous dispatches in Grand Central Dispatch (GCD) in Swift.

    add Podfile

    pod 'AsyncSwift'
    

    Then,you can use it like this.

    let seconds = 3.0
    Async.main(after: seconds) {
    print("Is called after 3 seconds")
    }.background(after: 6.0) {
    print("At least 3.0 seconds after previous block, and 6.0 after Async code is called")
    }
    
    0 讨论(0)
提交回复
热议问题