मुख्य थ्रेड पर एक विधि कॉलिंग?


83

सबसे पहले मैं iphone के लिए कोड लिख रहा हूँ। मुझे उपयोग किए बिना मुख्य थ्रेड पर एक विधि को कॉल करने में सक्षम होने की आवश्यकता है performSelectorOnMainThread। कारण है कि मैं उपयोग नहीं करना चाहता performSelectorOnMainThreadहै कि यह समस्या का कारण बनता है जब मैं इकाई परीक्षण के लिए एक नकली बनाने की कोशिश कर रहा हूँ।

[self performSelectorOnMainThread:@Selector(doSomething) withObject:nil];

समस्या यह है कि मेरा नकली कॉल करना जानता है, doSomethingलेकिन यह नहीं जानता कि कॉल कैसे करें performSelectorOnMainThread

तो कोई उपाय?

जवाबों:


274

उद्देश्य सी

dispatch_async(dispatch_get_main_queue(), ^{
    [self doSomething];
});

तीव्र

DispatchQueue.main.async {
    self.doSomething()
}

लिगेसी स्विफ्ट

dispatch_async(dispatch_get_main_queue()) {
    self.doSomething()
}

आपने अभी-अभी स्विफ्ट 3 कोड के साथ मेरा दिन बनाया है। धन्यवाद!
फेलिप बलुडिनो

ब्लॉक में सीधे स्वयं का उपयोग नहीं करना अच्छा अभ्यास है। इसके बजाय इसके कमजोर संदर्भ का उपयोग करें।
जगेन २ J ’१

2

सॉफ्टवेयर में एक कहावत है कि अप्रत्यक्ष की एक परत को जोड़ने से लगभग कुछ भी ठीक हो जाएगा।

क्या doSomething विधि एक अप्रत्यक्ष शेल है जो केवल एक PerformSelectorOnMainThread करता है जो वास्तव में कुछ काम करने के लिए वास्तव में_आवेदन विधि को कॉल करता है। या, यदि आप अपने doSomething विधि को बदलना नहीं चाहते हैं, तो मॉक टेस्ट यूनिट को कुछ समान करने के लिए doSomething_redirect_shell विधि को कॉल करें।


1

यहाँ स्विफ्ट में ऐसा करने का एक बेहतर तरीका है:

runThisInMainThread { () -> Void in
    // Run your code
    self.doSomething()
}

func runThisInMainThread(block: dispatch_block_t) {
    dispatch_async(dispatch_get_main_queue(), block)
}

मेरे रेपो में इसका एक मानक कार्य के रूप में समावेश है, इसे देखें : https://github.com/goktugyil/EZSwiftExtensions


यह किसी भी तरह से बेहतर नहीं है, आपने एक ऐसा फ़ंक्शन बनाया है जो एक दूसरे को कॉल करने के अलावा कुछ नहीं करता है। वैसे स्विफ्ट सिंटैक्स को और सरल बनाया जा सकता है "() -> शून्य में" की आवश्यकता नहीं है
aryaxt

इसका अधिक मानवीय पठनीय / लेखन योग्य है। हाँ स्वतः पूर्ण "() -> शून्य में" जोड़ता है। शून्य> शून्य क्लोजर में इस स्वत: पूर्ण व्यवहार को अक्षम करने के लिए वैसे भी क्या है?
एसकर्रॉथ

विधि नाम आपको भ्रामक लग सकता है, ऐसा लगता है कि ब्लॉक को मुख्य धागे पर तुरंत निष्पादित किया जाएगा, लेकिन यह सच नहीं है। dispatch_async मुख्य कतार पर कोड के ब्लॉक को अगले रनलूप में जोड़ता है, यह महत्वपूर्ण व्यवहार उस विधि के पीछे छिपा हुआ है जिसे "runThisInMainThread
aryaxt

1
यह अपेक्षित व्यवहार है, dispatch_async कतार के अंत में कोड जोड़ता है। यदि आप चाहते हैं कि इसे तुरंत बुलाया जाए तो आपको इसके बजाय डिस्पैच_संकल्प करना चाहिए। यदि आप उस थ्रेड के लिए एक कतार पर dispatch_sync करते हैं जो आप पहले से ही हैं, तो यह थ्रेड लॉक का कारण बनता है। आपके उदाहरण में प्रिंटों का क्रम "ए", "सी", "बी" हैं। ए और सी को 1 रनअप में निष्पादित किया जा रहा है क्योंकि वे एक ही दायरे में हैं। b को कतार के अंत में जोड़ा जाता है इसलिए इसे कभी-कभी बाद में कहा जाता है जब कतार में अन्य मौजूदा आइटम पूर्ण हो जाते हैं
aryaxt

1
@Esqarrouth - क्या आप dispatch_asyncइसे कॉल करने के बाद अपना अवरुद्ध कोड सुनिश्चित करते हैं ? इसके asyncबजाय का उपयोग करने के पूरे बिंदु को syncअवरुद्ध नहीं है जो निम्नानुसार है। (बेशक, blockकोड मुख्य कोड पर कुछ और ब्लॉक करेगा , क्योंकि पूछे जाने वाले कोड का बिंदु मुख्य धागे पर निष्पादित करना है। यदि आप पृष्ठभूमि कोड चलाना चाहते हैं, तो आप एक अलग कतार के लिए कहेंगे। नहीं dispatch_get_main_queue।)
टूलमेकरसेव

1

और अब स्विफ्ट 3 में:

DispatchQueue.main.async{
   self.doSomething()
}

-4
// Draw Line
    func drawPath(from polyStr: String){
        DispatchQueue.main.async {
            let path = GMSPath(fromEncodedPath: polyStr)
            let polyline = GMSPolyline(path: path)
            polyline.strokeWidth = 3.0
            polyline.strokeColor = #colorLiteral(red: 0.05098039216, green: 0.5764705882, blue: 0.2784313725, alpha: 1)
            polyline.map = self.mapVu // Google MapView
        }

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