ios - dispatch_after-GCD في سريع؟




swift grand-central-dispatch (13)

1) أضف هذه الطريقة كجزء من ملحق UIViewController.

extension UIViewController{
func runAfterDelay(delay: NSTimeInterval, block: dispatch_block_t) {
        let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
        dispatch_after(time, dispatch_get_main_queue(), block)
    }
}

اتصل بهذه الطريقة على VC:

    self.runAfterDelay(5.0, block: {
     //Add code to this block
        print("run After Delay Success")
    })

2) performSelector ("yourMethod Name" ، withObject: nil ، afterDelay: 1)

3)

override func viewWillAppear(animated: Bool) {

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2), dispatch_get_main_queue(), { () -> () in
    //Code Here
})

// نموذج مدمج

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 2), dispatch_get_main_queue()) {
    //Code here
}

}

لقد مرت iBook من Apple ولم أستطع العثور على أي تعريف له:

يمكن للشخص شرح هيكل dispatch_after ؟

dispatch_after(<#when: dispatch_time_t#>, <#queue: dispatch_queue_t?#>, <#block: dispatch_block_t?#>)

أنا أستخدم dispatch_after كثير من الأحيان أنني كتبت وظيفة الأداة المساعدة ذات المستوى الأعلى لجعل بناء الجملة أكثر بساطة:

func delay(delay:Double, closure:()->()) {
    dispatch_after(
        dispatch_time(
            DISPATCH_TIME_NOW,
            Int64(delay * Double(NSEC_PER_SEC))
        ),
        dispatch_get_main_queue(), closure)
}

والآن يمكنك التحدث على هذا النحو:

delay(0.4) {
    // do stuff
}

واو ، لغة يمكنك من خلالها تحسين اللغة. ماذا يمكن أن يكون أفضل؟

Update for Swift 3، Xcode 8 Seed 6

يبدو أنه لا يكاد يزعج نفسه ، بعد أن قاموا بتحسين بنية الاتصال:

func delay(_ delay:Double, closure:@escaping ()->()) {
    let when = DispatchTime.now() + delay
    DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}

الآن أكثر من السكر النحوي لارسال غير متزامن في جراند سنترال ديسباتش (GCD) في سويفت.

إضافة Podfile

pod 'AsyncSwift'

ثم ، يمكنك استخدامه على هذا النحو.

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")
}

طريقة أخرى هي تمديد مزدوج مثل هذا:

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

ثم يمكنك استخدامه على النحو التالي:

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

أنا أحب وظيفة التأخير مات ولكن فقط من التفضيل فما استقاموا لكم فاستقيموا بدلا للحد من إغلاق الإغلاق حولها.


فكرة أوضح عن الهيكل:

dispatch_after(when: dispatch_time_t, queue: dispatch_queue_t, block: dispatch_block_t?)

dispatch_time_t هو UInt64 . إن dispatch_queue_t هو في الواقع نوع مستعار إلى NSObject ، ولكن يجب عليك فقط استخدام طرق GCD المألوفة للحصول على قوائم الانتظار. الكتلة هي إغلاق سويفت. على وجه التحديد ، يتم تعريف dispatch_block_t باسم () -> Void ، وهو ما يعادل () -> () .

استخدام المثال:

let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) {
    print("test")
}

تصحيح:

أوصي باستخدام وظيفة delay لطيف جدا @ مات .

تعديل 2:

في Swift 3 ، سيكون هناك أغلفة جديدة لـ GCD. انظر هنا: https://github.com/apple/swift-evolution/blob/master/proposals/0088-libdispatch-for-swift3.md

سيتم كتابة المثال الأصلي كما يلي في Swift 3:

let deadlineTime = DispatchTime.now() + .seconds(1)
DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
    print("test")
}

لاحظ أنه يمكنك كتابة تعريف deadlineTime كـ DispatchTime.now() + 1.0 والحصول على نفس النتيجة بسبب تجاوز عامل التشغيل + كما يلي (وبالمثل لـ - ):

  • func +(time: DispatchTime, seconds: Double) -> DispatchTime
  • func +(time: DispatchWalltime, interval: DispatchTimeInterval) -> DispatchWalltime

هذا يعني أنه إذا لم تستخدم enum DispatchTimeInterval واكتب فقط رقمًا ، يفترض أنك تستخدم ثانية.


لدى Apple مقتطف dispatch_after من أجل Objective-C :

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    <#code to be executed after a specified delay#>
});

في ما يلي المقتطف نفسه الذي تم نقله إلى Swift 3:

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + <#delayInSeconds#>) {
  <#code to be executed after a specified delay#>
}

للتوسع على إجابة سيزاري ، التي ستنفذ بعد 1 nanosecond ، اضطررت للقيام بما يلي بعد 4 و نصف ثانية.

    let delay = 4.5 * Double(NSEC_PER_SEC)
    let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
    dispatch_after(time, dispatch_get_main_queue(), block)

التعديل: اكتشفت أن شفرتي الأصلية كانت خاطئة بعض الشيء. تؤدي الكتابة الضمنية إلى خطأ في الترجمة إذا لم تقم بإدخال NSEC_PER_SEC إلى "مزدوج".

إذا كان أي شخص يمكن أن يقترح حلا أكثر أمنا سأكون حريصا على سماع ذلك.

== تحديث ل Swift 3 ==

هذا سهل جدا وأنيق في Swift 3:

    DispatchQueue.main.asyncAfter(deadline: .now() + 4.5) {
        // ...
    }

مساعد آخر لتأخير شفرتك التي تكون 100٪ سويفت في الاستخدام ويسمح اختياريًا باختيار مؤشر ترابط مختلف لتشغيل شفرتك المتأخرة من:

public func delay(bySeconds seconds: Double, dispatchLevel: DispatchLevel = .main, closure: @escaping () -> Void) {
    let dispatchTime = DispatchTime.now() + seconds
    dispatchLevel.dispatchQueue.asyncAfter(deadline: dispatchTime, execute: closure)
}

public enum DispatchLevel {
    case main, userInteractive, userInitiated, utility, background
    var dispatchQueue: DispatchQueue {
        switch self {
        case .main:                 return DispatchQueue.main
        case .userInteractive:      return DispatchQueue.global(qos: .userInteractive)
        case .userInitiated:        return DispatchQueue.global(qos: .userInitiated)
        case .utility:              return DispatchQueue.global(qos: .utility)
        case .background:           return DispatchQueue.global(qos: .background)
        }
    }
}

الآن يمكنك ببساطة تأخير الرمز الخاص بك على الموضوع الرئيسي مثل هذا:

delay(bySeconds: 1.5) { 
    // delayed code
}

إذا كنت ترغب في تأخير التعليمة البرمجية الخاصة بك إلى مؤشر ترابط مختلف :

delay(bySeconds: 1.5, dispatchLevel: .background) { 
    // delayed code that will run on background thread
}

إذا كنت تفضل إطارًا يحتوي أيضًا على بعض الميزات المفيدة ، HandySwift الخروج من HandySwift . يمكنك إضافته إلى مشروعك عبر قرطاج ثم استخدامه كما في الأمثلة السابقة ، على سبيل المثال:

import HandySwift    

delay(bySeconds: 1.5) { 
    // delayed code
}

بناء الجملة مات هو لطيف جدا ، وإذا كنت بحاجة إلى إبطال الكتلة ، قد ترغب في استخدام هذا:

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)
    }
}

استخدم على النحو التالي

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

credits

يبدو الرابط أعلاه بانخفاض. كود Objc الأصلي من جيثب


أبسط الحلول في Swift 3.0 و Swift 4.0

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

استعمال

delayWithSeconds(1) {
   //Do something
}

جارٍ تأخير اتصال GCD باستخدام asyncAfter سريعًا

let delayQueue = DispatchQueue(label: "com.theappmaker.in", qos: .userInitiated)
let additionalTime: DispatchTimeInterval = .seconds(2)

يمكننا التأخير كـ microseconds ** ، ميلي ثانية ، nanoseconds

delayQueue.asyncAfter(deadline: .now() + 0.60) {
    print(Date())
}

delayQueue.asyncAfter(deadline: .now() + additionalTime) {
    print(Date())
}

سويفت 3 و 4:

يمكنك إنشاء ملحق على DispatchQueue وإضافة تأخير وظيفة يستخدم الدالة DispatchQueue asyncAfter داخليًا

extension DispatchQueue {
    static func delay(_ delay: DispatchTimeInterval, closure: @escaping () -> ()) {
        let timeInterval = DispatchTime.now() + delay
        DispatchQueue.main.asyncAfter(deadline: timeInterval, execute: closure)
    }
}

استعمال:

DispatchQueue.delay(.seconds(1)) {
    print("This is after delay")
}

في Swift 3.0

طوابير الإرسال

  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")
        })
    }

إرسال بعد 5 ثوان

    DispatchQueue.main.after(when: DispatchTime.now() + 5) {
        print("Dispatch after 5 sec")
    }




grand-central-dispatch