मैं स्विफ्ट 3, स्विफ्ट 4, और उससे आगे आदि में कैसे डिस्पैच_सुंक, डिस्पैच_सुंक, डिस्पैच_ आफ्टर, कैसे करूं?


243

मेरे पास स्विफ्ट 2.x (या यहां तक ​​कि 1.x) परियोजनाओं में बहुत सारे कोड हैं जो इस तरह दिखता है:

// Move to a background thread to do some long running work
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
    let image = self.loadOrGenerateAnImage()
    // Bounce back to the main thread to update the UI
    dispatch_async(dispatch_get_main_queue()) {
        self.imageView.image = image
    }
}

या निष्पादन में देरी करने के लिए इस तरह से सामान:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.5 * Double(NSEC_PER_SEC))), dispatch_get_main_queue()) {
    print("test")
}

या ग्रैंड सेंट्रल डिस्पैच एपीआई के अन्य उपयोगों के किसी भी प्रकार ...

अब जब मैंने स्विफ्ट 3 के लिए एक्सकोड 8 (बीटा) में अपना प्रोजेक्ट खोला है, तो मुझे सभी प्रकार की त्रुटियां हैं। उनमें से कुछ मेरे कोड को ठीक करने की पेशकश करते हैं, लेकिन सभी फिक्सिंग कोड काम नहीं करते हैं। मैं इस बारे में क्या करूं?


यहाँ उत्तर दिया गया: stackoverflow.com/questions/37805885/…
t1ser

जवाबों:


343

शुरुआत के बाद से, Swift ने ObjC और C को अधिक Swifty बनाने के लिए कुछ सुविधाएं प्रदान की हैं, प्रत्येक संस्करण के साथ अधिक जोड़ रहा है। अब, स्विफ्ट 3 में, नया "इम्पोर्ट फ़ॉर मेम्बर" फ़ीचर C API की कुछ शैलियों के साथ फ्रेमवर्क देता है - जहाँ आपके पास एक डेटा प्रकार होता है जो एक वर्ग की तरह काम करता है, और इसके साथ काम करने के लिए वैश्विक कार्यों का एक गुच्छा - स्विफ्ट-देशी एपीआई की तरह कार्य करें। डेटा प्रकार स्विफ्ट कक्षाओं के रूप में आयात करते हैं, उनके संबंधित वैश्विक फ़ंक्शन उन वर्गों पर विधियों और गुणों के रूप में आयात करते हैं, और कुछ संबंधित चीजें जैसे स्थिरांक सेट उपयुक्त हो सकते हैं।

Xcode 8 / स्विफ्ट 3 बीटा में, Apple ने इस सुविधा (कुछ अन्य के साथ) को डिस्पैच ढांचे को और अधिक Swifty बनाने के लिए लागू किया है। (और कोर ग्राफिक्स , भी।) यदि आप स्विफ्ट ओपन-सोर्स प्रयासों का पालन कर रहे हैं, तो यह खबर नहीं है , लेकिन अब यह पहली बार है जब यह Xcode का हिस्सा है।

किसी भी प्रोजेक्ट को स्विफ्ट 3 में ले जाने पर आपका पहला कदम इसे Xcode 8 में खोलना और मेनू में Edit> Convert> To Current Swift Syntax ... को चुनना होगा । यह सभी नामांकित एपीआई और अन्य परिवर्तनों के लिए एक बार में आवश्यक परिवर्तनों के (आपकी समीक्षा और अनुमोदन के साथ) लागू होगा। (अक्सर, कोड की एक पंक्ति इन परिवर्तनों में से एक से अधिक बार प्रभावित होती है, इसलिए त्रुटि को ठीक करने के लिए प्रतिक्रिया-व्यक्तिगत रूप से सब कुछ ठीक से संभाल सकती है।)

नतीजा यह है कि पृष्ठभूमि और वापस काम करने के लिए शेख़ी के लिए सामान्य पैटर्न अब इस तरह दिखता है:

// Move to a background thread to do some long running work
DispatchQueue.global(qos: .userInitiated).async {
    let image = self.loadOrGenerateAnImage()
    // Bounce back to the main thread to update the UI
    DispatchQueue.main.async {
        self.imageView.image = image
    }
}

ध्यान दें कि हम .userInitiatedपुराने DISPATCH_QUEUE_PRIORITYस्थिरांक के बजाय उपयोग कर रहे हैं । सेवा की गुणवत्ता (क्यूओएस) विनिर्देशक ओएस एक्स 10.10 / आईओएस 8.0 में पेश किए गए थे, जो सिस्टम को काम को प्राथमिकता देने और पुराने प्राथमिकता वाले विनिर्देशकों को हटाने के लिए एक स्पष्ट रास्ता प्रदान करते हैं। विवरण के लिए पृष्ठभूमि के काम और ऊर्जा दक्षता पर Apple के डॉक्स देखें।

वैसे, यदि आप काम को व्यवस्थित करने के लिए अपनी खुद की कतारें रख रहे हैं, तो एक प्राप्त करने का तरीका अब इस तरह दिखता है (नोटिस जो कि DispatchQueueAttributesएक है OptionSet, इसलिए आप विकल्पों को संयोजित करने के लिए संग्रह-शैली के शाब्दिक का उपयोग करते हैं):

class Foo { 
    let queue = DispatchQueue(label: "com.example.my-serial-queue",
                           attributes: [.serial, .qosUtility])
    func doStuff() {
        queue.async {
            print("Hello World")
        }
    }
}

dispatch_afterबाद में काम करने के लिए उपयोग करना ? यह कतारों पर एक विधि है, और यह एक लेता है DispatchTime, जिसमें विभिन्न संख्यात्मक प्रकारों के लिए ऑपरेटर होते हैं ताकि आप बस संपूर्ण या आंशिक जोड़ जोड़ सकें:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { // in half a second...
    print("Are we there yet?")
}

आप Xcode 8 में इसका इंटरफ़ेस खोलकर नए डिस्पैच एपीआई के चारों ओर अपना रास्ता पा सकते हैं - डिस्पैच मॉड्यूल को खोजने के लिए जल्दी से ओपन का उपयोग करें, या DispatchQueueअपने स्विफ्ट प्रोजेक्ट / खेल के मैदान में एक प्रतीक (जैसे ) डालें और इसे क्लिक करें, फिर चारों ओर झुकें वहां से मॉड्यूल। (आप एप्पल के स्पिफी न्यू एपीआई रेफरेंस वेबसाइट और इन-एक्सकोड डॉक दर्शक में स्विफ्ट डिस्पैच एपीआई पा सकते हैं , लेकिन ऐसा लगता है कि सी संस्करण से डॉक सामग्री अभी तक इसमें स्थानांतरित नहीं हुई है।)

अधिक सुझावों के लिए माइग्रेशन गाइड देखें ।


3
Xcode 8 बीटा 6 के लिए, .serial विशेषता समाप्त हो गई है और डिफ़ॉल्ट व्यवहार - फ़ोरम .developer.apple.com
message

6
XCode 8.1 के बाद से इसे अपडेट की आवश्यकता है .. गुण लेबल गायब हो गया है और इसके स्थान पर हम 'DispatchQueue.global (qos: .background) .async' का उपयोग कर सकते हैं
माइक एम

2
अद्भुत जवाब। वास्तव में मुझे इसके चारों ओर अपना सिर लाने में मदद की।
मोहसिन ख़ुबीब अहमद

मुझे qos:इसके बजाय का उपयोग करना थाattributes:
इस्लाम Q.

उदाहरण myQueue.async {में ऐसा नहीं होना चाहिए class Foo?
टीकामा

142

Xcode 8 में बीटा 4 काम नहीं करता है ...

उपयोग:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
    print("Are we there yet?")
}

async के लिए दो तरीके:

DispatchQueue.main.async {
    print("Async1")
}

DispatchQueue.main.async( execute: {
    print("Async2")
})

तो यह UI ब्लॉक नहीं करता है?
user25

72

यह एक के लिए अच्छा उदाहरण है Swift 4के बारे में async:

DispatchQueue.global(qos: .background).async {
    // Background Thread
    DispatchQueue.main.async {
        // Run UI Updates or call completion block
    }
}

Hi DispatchQueue.main.async {// रन यूआई अपडेट्स} बैकग्राउंड थ्रेड से पहले निष्पादित हो रही है
उमा अचंता



26

स्विफ्ट 5.2, 4 और बाद में

मुख्य और पृष्ठभूमि कतार

let main = DispatchQueue.main
let background = DispatchQueue.global()
let helper = DispatchQueue(label: "another_thread") 

Async और सिंक थ्रेड्स के साथ काम करना !

 background.async { //async tasks here } 
 background.sync { //sync tasks here } 

Async थ्रेड्स मुख्य थ्रेड के साथ काम करेंगे।

निष्पादित करते समय सिंक थ्रेड्स मुख्य थ्रेड को ब्लॉक कर देंगे।


1
और आप मुख्य धागे (UI) को अवरुद्ध किए बिना सिंक थ्रेड्स का उपयोग कैसे करेंगे ?? मैं पृष्ठभूमि में चीजों की एक पंक्ति को निष्पादित करना चाहता हूं - लेकिन एक चीज़ों को एक के बाद एक सिंक तरीके से निष्पादित किया जाना चाहिए। इस समय के दौरान यूआई उत्तरदायी रहना चाहिए .... आप ऐसा कैसे करेंगे?
आईकेके

NSOperationQueue का उपयोग करें। जो आपके प्रत्येक कार्य को एक NSOperation का प्रतिनिधित्व करता है। संदर्भ देखें stackoverflow.com/a/19746890/5215474
सरंजिथ

12

स्विफ्ट 4.1 और 5. हम अपने कोड में कई स्थानों पर कतारों का उपयोग करते हैं। इसलिए, मैंने सभी कतारों के साथ थ्रेड्स क्लास बनाई। यदि आप थ्रेड्स क्लास का उपयोग नहीं करना चाहते हैं तो आप क्लास विधियों से वांछित कतार कोड कॉपी कर सकते हैं।

class Threads {

  static let concurrentQueue = DispatchQueue(label: "AppNameConcurrentQueue", attributes: .concurrent)
  static let serialQueue = DispatchQueue(label: "AppNameSerialQueue")

  // Main Queue
  class func performTaskInMainQueue(task: @escaping ()->()) {
    DispatchQueue.main.async {
      task()
    }
  }

  // Background Queue
  class func performTaskInBackground(task:@escaping () throws -> ()) {
    DispatchQueue.global(qos: .background).async {
      do {
        try task()
      } catch let error as NSError {
        print("error in background thread:\(error.localizedDescription)")
      }
    }
  }

  // Concurrent Queue
  class func perfromTaskInConcurrentQueue(task:@escaping () throws -> ()) {
    concurrentQueue.async {
      do {
        try task()
      } catch let error as NSError {
        print("error in Concurrent Queue:\(error.localizedDescription)")
      }
    }
  }

  // Serial Queue
  class func perfromTaskInSerialQueue(task:@escaping () throws -> ()) {
    serialQueue.async {
      do {
        try task()
      } catch let error as NSError {
        print("error in Serial Queue:\(error.localizedDescription)")
      }
    }
  }

  // Perform task afterDelay
  class func performTaskAfterDealy(_ timeInteval: TimeInterval, _ task:@escaping () -> ()) {
    DispatchQueue.main.asyncAfter(deadline: (.now() + timeInteval)) {
      task()
    }
  }
}

उदाहरण मुख्य कतार का उपयोग दिखा रहा है।

override func viewDidLoad() {
    super.viewDidLoad()
     Threads.performTaskInMainQueue {
        //Update UI
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.