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




swift grand-central-dispatch (17)

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

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 واكتب فقط رقمًا ، يفترض أنك تستخدم ثانية.

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

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

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

أنا دائما يفضل استخدام التمديد بدلا من الوظائف المجانية.

سويفت 4

public extension DispatchQueue {

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

  class func performAction(after seconds: TimeInterval, callBack: @escaping (() -> Void) ) {
    DispatchQueue.delay(delay: seconds) {
      callBack()
    }
  }

}

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

DispatchQueue.performAction(after: 0.3) {
  // Code Here
}

للتوسع على إجابة سيزاري ، التي ستنفذ بعد 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) {
        // ...
    }

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

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

استعمال

delayWithSeconds(1) {
   //Do something
}

على الرغم من أنه ليس السؤال الأصلي الذي طرحه البروتوكول الاختياري ، فقد تم وضع علامة على بعض الأسئلة ذات الصلة بـ NSTimer كتكرار لهذا السؤال ، لذا من المفيد NSTimer إجابة NSTimer هنا.

NSTimer مقابل dispatch_after

  • NSTimer هو مستوى أعلى في حين dispatch_after هو مستوى منخفض أكثر.
  • NSTimer أسهل للإلغاء. يتطلب إلغاء dispatch_after كتابة المزيد من التعليمات البرمجية .

تأخير مهمة مع NSTimer

قم NSTimer مثيل NSTimer .

var timer = NSTimer()

ابدأ الموقت مع التأخير الذي تحتاجه.

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

إضافة دالة يتم استدعاؤها بعد التأخير (باستخدام أي اسم استخدمته لمعلمة selector أعلاه).

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

ملاحظات

  • إذا كنت بحاجة إلى إلغاء الإجراء قبل حدوثه ، timer.invalidate() ببساطة بالاتصال على timer.invalidate() .
  • لتكرار استخدام الإجراء المتكرر repeats: true .
  • إذا كان لديك حدث لمرة واحدة دون الحاجة إلى الإلغاء ، فلا داعي لإنشاء متغير مثيل timer . سوف يكفي ما يلي:

    NSTimer.scheduledTimerWithTimeInterval(2.0, target: self, selector: #selector(delayedAction), userInfo: nil, repeats: false) 
    
  • انظر جوابي الكامل here .


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

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

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


الآن أكثر من السكر النحوي لارسال غير متزامن في جراند سنترال ديسباتش (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")
}

سويفت 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 4 طريقة قصيرة جدًا لإجراء ذلك:

Timer.scheduledTimer(withTimeInterval: 2, repeats: false) { (timer) in
    // Your stuff here
    print("hello")
}

هذا العمل بالنسبة لي.

سويفت 3:

let time1 = 8.23
let time2 = 3.42

// Delay 2 seconds

DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
    print("Sum of times: \(time1 + time2)")
}

ج موضوعية:

CGFloat time1 = 3.49;
CGFloat time2 = 8.13;

// Delay 2 seconds

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    CGFloat newTime = time1 + time2;
    NSLog(@"New time: %f", newTime);
});

جارٍ تأخير اتصال 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())
}

استخدم هذا الرمز لتنفيذ بعض المهام المتعلقة بـ UI بعد 2.0 ثانية.

            let delay = 2.0
            let delayInNanoSeconds = dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)))
            let mainQueue = dispatch_get_main_queue()

            dispatch_after(delayInNanoSeconds, mainQueue, {

                print("Some UI related task after delay")
            })

سويفت 3.0 نسخة

بعد إغلاق وظيفة تنفيذ بعض المهام بعد التأخير في الموضوع الرئيسي.

func performAfterDelay(delay : Double, onCompletion: @escaping() -> Void){

    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + delay, execute: {
       onCompletion()
    })
}

استدعاء هذه الوظيفة مثل:

performAfterDelay(delay: 4.0) {
  print("test")
}

لدى 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) أضف هذه الطريقة كجزء من ملحق 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
}

}


أنا أستخدم 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)
}

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

حسب Swift 2.2

كل ما عليك هو كتابة رمز خط 2 وستحصل على سلسلة الانقسام.

let fullName = "FirstName LastName"
var splitedFullName = fullName.componentsSeparatedByString(" ")
print(splitedFullName[0])
print(splitedFullName[1]) 

استمتع. :)





ios swift grand-central-dispatch