मैं स्विफ्ट 3, 4, और 5 में जीसीडी कैसे भेजूं?


445

स्विफ्ट 2 में, मैं dispatch_afterभव्य केंद्रीय प्रेषण का उपयोग करते हुए कार्रवाई में देरी करने में सक्षम था :

var dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC))) 
dispatch_after(dispatchTime, dispatch_get_main_queue(), { 
    // your function here 
})

लेकिन यह स्विफ्ट 3 के बाद से संकलित नहीं लगता है। आधुनिक स्विफ्ट में इसे लिखने का पसंदीदा तरीका क्या है?


6
माइग्रेशन प्रक्रिया के बारे में अधिक जानकारी यहां पाई जा सकती है: https://swift.org/migration-guide/ इस सवाल के लिए "डिस्पैच" खंड प्रासंगिक है
tonik12

क्या आपका प्रश्न होना चाहिए UInt64?
हनी

जवाबों:


1125

वाक्य विन्यास बस है:

// to run something in 0.1 seconds

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
    // your code here
}

ध्यान दें, उपर्युक्त वाक्यविन्यास secondsएक Doubleभ्रम के स्रोत के रूप में लगता है (क्योंकि हम nsec जोड़ने के आदी थे)। वह "जोड़ सेकंड Double" के रूप में "वाक्य रचना काम करती है क्योंकि deadlineएक है DispatchTime, पर्दे के पीछे, एक +ऑपरेटर है जो एक ले जाएगा Doubleऔर उस कई सेकंड को जोड़ देगा DispatchTime:

public func +(time: DispatchTime, seconds: Double) -> DispatchTime

लेकिन, यदि आप वास्तव में, msec μs, या करने के लिए nsec के एक पूर्णांक संख्या जोड़ना चाहते हैं DispatchTime, तो आप भी एक जोड़ सकते हैं DispatchTimeIntervalएक करने के लिए DispatchTime। इसका मतलब है कि आप कर सकते हैं:

DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(500)) {
    os_log("500 msec seconds later")
}

DispatchQueue.main.asyncAfter(deadline: .now() + .microseconds(1_000_000)) {
    os_log("1m μs seconds later")
}

DispatchQueue.main.asyncAfter(deadline: .now() + .nanoseconds(1_500_000_000)) {
    os_log("1.5b nsec seconds later")
}

वर्ग +में ऑपरेटर के लिए इस अलग अधिभार विधि के कारण ये सभी मूल रूप से काम करते हैं DispatchTime

public func +(time: DispatchTime, interval: DispatchTimeInterval) -> DispatchTime

यह पूछा गया था कि किसी को भेजे गए कार्य को रद्द करने के बारे में कैसे जाना जाता है। ऐसा करने के लिए, का उपयोग करें DispatchWorkItem। उदाहरण के लिए, यह एक कार्य शुरू करता है जो पाँच सेकंड में आग लगा देगा, या यदि दृश्य नियंत्रक को खारिज कर दिया जाता है और उसे हटा दिया जाता है, तो deinitयह कार्य रद्द कर देगा:

class ViewController: UIViewController {

    private var item: DispatchWorkItem?

    override func viewDidLoad() {
        super.viewDidLoad()

        item = DispatchWorkItem { [weak self] in
            self?.doSomething()
            self?.item = nil
        }

        DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: item!)
    }

    deinit {
        item?.cancel()
    }

    func doSomething() { ... }

}

में [weak self]कैप्चर सूची के उपयोग पर ध्यान दें DispatchWorkItem। एक मजबूत संदर्भ चक्र से बचने के लिए यह आवश्यक है। यह भी ध्यान दें कि यह एक पूर्व-निरस्तीकरण नहीं करता है, बल्कि कार्य को शुरू करने से रोकता है यदि यह पहले से ही नहीं है। लेकिन अगर यह cancel()कॉल शुरू होने तक पहले ही शुरू हो गया है , तो ब्लॉक अपने निष्पादन को समाप्त कर देगा (जब तक कि आप मैन्युअल रूप isCancelledसे ब्लॉक के अंदर जांच नहीं कर रहे हैं )।


5
उस ओर इशारा करने के लिए धन्यवाद, और वास्तव में flex.org/migration-guide में उस परिवर्तन को हाथ से करने की आवश्यकता का उल्लेख है।
मैट

1
मुझे माफ करें। यहाँ बहुत देर हो चुकी है :)। सोचा कि सभी गड़बड़ वास्तव में जाना चाहिए, लेकिन छलांग नहीं लिया। IMO "सरल" समाधान एक-सच्चा समाधान है।
तोबिसडम

1
@ रोब मैं इसे रद्द करने के बारे में कैसे जाऊंगा? धन्यवाद।
केमिकोफा घोस्ट

ठीक है, तो आप एक गतिशील प्रतीक्षा कैसे जोड़ सकते हैं? उदाहरण के लिए, मेरे पास एक संख्या है: फ्लोट = 1.0। और .now () + .milliseconds (नंबर) काम नहीं करता है। न ही डबल (संख्या) करता है। मेरे द्वारा इसका निर्धारण नहीं किया जा सकता।
केजेल

2
DispatchTimeIntervalRenditions, जैसे .millisecondsकी आवश्यकता होती है Int। लेकिन अगर सिर्फ सेकंड जोड़ना, मैं उपयोग करेंगे Double, जैसे let n: Double = 1.0; queue.asyncAfter(deadline: .now() + n) { ... }
रॉब

128

स्विफ्ट 4:

DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) {
   // Code
}

समय के लिए .seconds(Int), .microseconds(Int)और .nanoseconds(Int)भी इस्तेमाल किया जा सकता है।


7
.millisecondsडबल से बेहतर है।
डॉनसॉन्ग

5
बहुत अच्छा। दूसरों के लिए एक नोट: आप किसी भी अन्य DispatchTimeIntervalएनम मूल्यों का भी उपयोग कर सकते हैं। case seconds(Int) case milliseconds(Int) case microseconds(Int) case nanoseconds(Int)
रॉ मैकएचर्न

@RobMacEachern, धन्यवाद अच्छा सुझाव मैं इसे जवाब में जोड़ देता हूं।
सेवरिसन

2
.milliseconds is better than Double. - मैं चाहता हूं कि एक टी-शर्ट पर;)।
क्रिस प्रिंस

58

यदि आप बस देरी समारोह में चाहते हैं

स्विफ्ट 4 और 5

func delay(interval: TimeInterval, closure: @escaping () -> Void) {
     DispatchQueue.main.asyncAfter(deadline: .now() + interval) {
          closure()
     }
}

आप इसका उपयोग कर सकते हैं जैसे:

delay(interval: 1) { 
    print("Hi!")
}

DispatchQueue.main.asyncAfter (समय सीमा:) काम नहीं करता है। यह कहता है कि यह अपने सुपरक्लास से किसी भी तरीके को अधिभारित नहीं करता है।
फैब्रीज़ियो बार्टोलोमुची

7
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1, execute: closure)सरल है।
डॉनसॉन्ग


5

स्वीकृत उत्तर का कुछ अलग स्वाद।

स्विफ्ट 4

DispatchQueue.main.asyncAfter(deadline: .now() + 0.1 + .milliseconds(500) + 
.microseconds(500) + .nanoseconds(1000)) {
                print("Delayed by 0.1 second + 500 milliseconds + 500 microseconds + 
                      1000 nanoseconds)")
 }

5

स्विफ्ट 4

आप DispatchQueue पर एक एक्सटेंशन बना सकते हैं और फ़ंक्शन विलंब जोड़ सकते हैं जो DispatchQueueआंतरिक रूप से asyncAfter फ़ंक्शन का उपयोग करता है

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

और उपयोग करें

DispatchQueue.delay(.milliseconds(10)) {
   print("task to be done")
}

2
यह @ रॉकडस्विफ्ट के उत्तर से कैसे भिन्न है?
ब्रैंडनस्क्रिप्ट 16

जैसा कि मैंने उल्लेख किया है कि प्रदर्शन के बाद asyncAfter फ़ंक्शन को लपेटता है जो पैरामीटर के रूप में देरी करता है और इसे बस निष्पादन के बाद कॉल करना आसान हो सकता है (देरी: 2) {}
Suhit Patil

डिफ़ॉल्ट रूप से क्लोजिंग पैरामीटर गैर-एस्केप हैं, @ एसेडिंग इंगित करता है कि क्लोजर पैरामीटर बच सकता है। जोड़ा @ संभावित दुर्घटना को बचाने के लिए बंद करने में बचने के पैरामीटर।
सुहित पाटिल

3

कॉल DispatchQueue.main.after(when: DispatchTime, execute: () -> Void)

मैं अत्यधिक 3 स्विफ्ट 3 का उपयोग करने के लिए Xcode टूल का उपयोग करने की सलाह दूंगा (संपादित करें> कन्वर्ट> वर्तमान स्विफ्ट सिंटैक्स में)। इसने मेरे लिए यह पकड़ लिया


3

स्विफ्ट 4.1 और एक्सकोड 9.4.1 में

सरल उत्तर है ...

//To call function after 5 seconds time
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
//Here call your function
}

3
निश्चित नहीं कि यह स्वीकृत उत्तर से अलग कैसे है?
ब्रैंडनस्क्रिप्ट 5


1

उत्तर में से कोई भी एक गैर-मुख्य धागे पर चलने का उल्लेख नहीं करता है, इसलिए मेरे 2 सेंट जोड़ रहा है।

पर मुख्य कतार (मुख्य थ्रेड)

let mainQueue = DispatchQueue.main
let deadline = DispatchTime.now() + .seconds(10)
mainQueue.asyncAfter(deadline: deadline) {
    // ...
}

या

DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + .seconds(10)) { 
    // ...
}

पर वैश्विक कतार (गैर मुख्य थ्रेड, QOS के आधार पर निर्दिष्ट)।

let backgroundQueue = DispatchQueue.global()
let deadline = DispatchTime.now() + .milliseconds(100)
backgroundQueue.asyncAfter(deadline: deadline, qos: .background) { 
    // ...
}

या

DispatchQueue.global().asyncAfter(deadline: DispatchTime.now() + .milliseconds(100), qos: .background) {
    // ...
}

0

इसने स्विफ्ट 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)")
}

5
निश्चित नहीं कि यह स्वीकृत उत्तर से कैसे भिन्न है?
ब्रांडनस्क्रिप्ट


0

इसे इस्तेमाल करे

let when = DispatchTime.now() + 1.5
    DispatchQueue.main.asyncAfter(deadline: when) {
        //some code
    }

निश्चित नहीं है कि यह प्रभावित उत्तर से कैसे भिन्न है?
ब्रैंडनस्क्रिप्ट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.