2015-07-07 6 views
6

नहीं दिख रहा है मेरे पास कुछ भारी कोड है जो लगभग 0.2 सेकंड तक चलता है।गतिविधि संकेतक

मैंने इस तरह की गतिविधि संकेतक स्थापित किया है; हालांकि, यह दिखाई नहीं देता है, लेकिन कोड पूरी होने तक पूरी स्क्रीन लगभग 0.2 सेकंड के लिए फ्रीज होती है।

func heavyWork() { 
    self.actvityIndicator.startAnimating() 

    ... 
    // heavy loop codes here 
    ... 

    self.activityIndicator.stopAnimating() 
} 

क्या यह गतिविधि संकेतक का उपयोग करने का सही तरीका है?

जब मैं बाहर टिप्पणी

// self.activityIndicator.stopAnimating() 

गतिविधि सूचक पता चलता है और वहाँ रहता है - कोड सही स्थापित कर रहे हैं।

लेकिन यूआई सही समय पर अपडेट नहीं किया जा रहा है।

जैसा कि मैंने कहा, स्क्रीन भारी कोड होने तक गतिविधि संकेतक को दिखाए बिना फ्रीज करता है।

+2

अपने 'भारी पाश code' एक पृष्ठभूमि धागा पर चल रहा है? भारी लूप कोड यूआई को गतिविधि संकेतक प्रदर्शित करने से रोक देगा। इसके अलावा यदि आप पृष्ठभूमि थ्रेड पर 'हेवीवॉर्क' को कॉल कर रहे हैं तो 'UI' अपडेट नहीं होना चाहिए क्योंकि यह मुख्य थ्रेड पर नहीं है। – sbarow

+0

यदि आप पृष्ठभूमि थ्रेड पर हैं, तो आप यूआई पर कुछ भी संशोधित नहीं कर सकते हैं; यदि आप मुख्य धागे पर हैं तो भारी काम करने के लिए यह सबसे अच्छा नहीं है। – holex

उत्तर

14

हो सकता है आप के बजाय इस तरह के पैटर्न के साथ पर ले जाने के लिए चाहते हैं:

func heavyWork() { 
    self.actvityIndicator.startAnimating() 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {() -> Void in 

     // ... 
     // heavy loop codes here 
     // ... 

     dispatch_async(dispatch_get_main_queue(), {() -> Void in 
      self.activityIndicator.stopAnimating() 
     }) 
    }); 
} 

के रूप में भारी काम एक पृष्ठभूमि सूत्र में होना चाहिए और आप एक मुख्य धागा के बाद पर यूआई अपडेट करना होगा।


नोट: जाहिर है यह आपfunc heavyWork() एक मुख्य थ्रेड पर फोन माना जाता है; यदि नहीं, तो आपको प्रारंभिक यूआई अपडेट को मुख्य थ्रेड में भी विचलित करने की आवश्यकता हो सकती है।

1

ऐसा इसलिए होता है क्योंकि आप मुख्य धागे पर भारी शुल्क कोड चला रहे हैं। इस तरह सिस्टम को कभी भी भारी दिनचर्या समाप्त होने तक ग्राफिक लेनदेन करने का मौका नहीं मिलता है। आपकी शुरुआत और रोक विधि एक ही समय में प्रतिबद्ध हैं।
इससे बचने के लिए आपको dispatch_queue पर भारी कर्तव्य विधि चलाना चाहिए, लेकिन ध्यान दें कि अधिकांश UIKit ऑब्जेक्ट्स थ्रेड सुरक्षित नहीं हैं और उन्हें मुख्य कतार पर फिर से प्रेषित किया जाना चाहिए।

4

यदि आप कुछ भारी कार्य करते समय ऐप को उत्तरदायी होना चाहते हैं, तो आपको इसे पृष्ठभूमि थ्रेड पर निष्पादित करने की आवश्यकता होगी।

यह मोटे तौर पर यहां क्या हो रहा है: आपके ऐप का मुख्य धागा रन लूप में निष्पादित होता है। प्रत्येक लूप पुनरावृत्ति की शुरुआत में, आईओएस किसी भी घटना के लिए जांच करता है (जैसे उपयोगकर्ता इंटरैक्शन, एनीमेशन के कारण बदलते विचार, टाइमर निकाल दिए जाते हैं, आदि) फिर निष्पादित करने के तरीकों का एक गुच्छा कतारबद्ध करता है। आईओएस तब जाता है और उन तरीकों में से प्रत्येक को निष्पादित करता है और फिर, सबकुछ पूरा हो जाने पर, यह प्रदर्शन को अपडेट करता है। फिर अगला रन लूप पुनरावृत्ति शुरू होता है। डिस्प्ले अपडेट करना महंगा है, इसलिए कोड की प्रत्येक पंक्ति निष्पादित होने के बाद आईओएस ऐसा नहीं कर सकता है।

तो अपने कोड के साथ, जब आप गतिविधि को शुरू करने के लिए संकेतक कहते हैं, यह आईओएस को बताता है कि प्रत्येक रन लूप पुनरावृत्ति के अंत में गतिविधि सूचक छवि को एनीमेशन अनुक्रम में अगली छवि में अपडेट करने की आवश्यकता होती है। फिर, आईओएस वर्तमान रन लूप पुनरावृत्ति के अंत तक पहुंचने से पहले, आप स्टॉप एनीमेटिंग को कॉल कर रहे हैं जो आईओएस को बताता है कि अब छवियों को अपडेट करने की आवश्यकता नहीं है। तो मूल रूप से आप इसे शुरू करने से पहले इसे रोकने के लिए कह रहे हैं।

आप ग्रैंड सेंट्रल डिस्पैच का उपयोग आसानी से एक अलग थ्रेड पर कोड चलाने के लिए कर सकते हैं।यह ध्यान रखना महत्वपूर्ण है कि UI के किसी भी अपडेट को मुख्य थ्रेड पर किया जाना चाहिए।

func heavyWork() { 
    self.activityIndicator.startAnimating() 

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) { 


     // Do heavy work here 


     dispatch_async(dispatch_get_main_queue()) { 
      // UI updates must be on main thread 
      self.activityIndicator.stopAnimating() 
     } 
    } 
} 

भी जब इस तरह के ऊपर के उदाहरण में के रूप में अतुल्यकालिक रूप से प्रोग्रामिंग, ध्यान दें, आप विधि है कि यह लागू में अतुल्यकालिक अनुभाग से एक मूल्य वापस नहीं लौट सकते। जैसे उपर्युक्त उदाहरण में, आप भारी कार्य() विधि से भारी काम का नतीजा वापस नहीं कर सकते हैं। ऐसा इसलिए है क्योंकि फ़ंक्शन एसिंक कोड को एक अलग थ्रेड पर चलाने के लिए शेड्यूल करता है, फिर तुरंत लौटाता है ताकि यह वर्तमान रन लूप पुनरावृत्ति के साथ जारी रख सके।

1

स्विफ्ट 4:

func heavyWork() { 
    self.actvityIndicator.startAnimating() 

    DispatchQueue.global(qos: .background).async { 

     // ... 
     // heavy loop codes here 
     // ... 

     DispatchQueue.main.async { 
      self.actvityIndicator.stopAnimating() 
     } 
    } 
} 
संबंधित मुद्दे