2012-05-07 16 views
9

मैं एक पेंटिंग ऐप पर काम कर रहा हूं जो प्रतिपादन के लिए कोरग्राफिक्स का उपयोग करता है। मेरी समस्या है, प्रदर्शन के लिए, मैं अद्यतनों को केवल उस दृश्य के कुछ हिस्सों तक सीमित करने की कोशिश कर रहा हूं जो बदल गए हैं। इसके लिए, मैं setNeedsDisplayInRect का उपयोग करता हूं: लेकिन कभी-कभी दृश्य अपनी संपूर्ण सामग्री को अपडेट करता है, जिससे स्टटरिंग होती है। यह तीसरी पीढ़ी के आईपैड पर विशेष रूप से स्पष्ट है, लेकिन यह सिम्युलेटर और आईपैड 2 में भी कम डिग्री तक होता है। मैं इस व्यवहार को हटाने की कोशिश कर रहा हूं।setNeedsDisplayInRect: पूरे दृश्य को अपडेट करने का कारण बनता है

समस्या का प्रदर्शन करने के लिए, मैंने एक्सकोड में टेम्पलेट का उपयोग करके एक सरल "एकल दृश्य" प्रोजेक्ट बनाया। एक कस्टम UIView सबक्लास बनाया गया है जिसे मैंने xib फ़ाइल में दृश्य नियंत्रक के दृश्य के रूप में सेट किया है।

जोड़ा इस UIViewController के लिए:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{ 
    // Asks that the view refreshes a smal rectangle 
    [self.view setNeedsDisplayInRect:CGRectMake(10, 10, 20, 20)]; 
} 

MyView को यह जोड़ा (मेरे कस्टम दृश्य):

- (void)drawRect:(CGRect)rect 
{ 
    // Just log what is being updated 
    NSLog(@"%@", NSStringFromCGRect(rect)); 
} 

और बस हो गया। यदि मैं ऐप को तीसरे दस आईपैड (वास्तविक डिवाइस) पर चलाता हूं, तो लॉग समय-समय पर (जैसे अक्सर) अपने एंटीरर्टी में खुद को पुनर्निर्मित करने का दृश्य दिखाते हैं। यह बहुत निराशाजनक है और मैं विचारों से बाहर हूं

अपडेट: यहां कुछ लॉग हैं। यह निश्चित रूप से पूर्ण दृश्य को कभी-कभी अपडेट किया जा रहा है। मैं इसे पूरी तरह से रोकने के लिए कोशिश कर रहा हूँ लेकिन समझ नहीं सकता कैसे करने के लिए ...

2012-05-04 08:34:01.851 TestUpdateArea[45745:707] {{0, 0}, {320, 460}} 
2012-05-04 08:34:30.184 TestUpdateArea[45745:707] {{0, 0}, {320, 460}} 
2012-05-04 08:34:30.197 TestUpdateArea[45745:707] {{0, 0}, {320, 460}} 
2012-05-04 08:34:30.215 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 
2012-05-04 08:34:30.226 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 
2012-05-04 08:34:30.242 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 
2012-05-04 08:34:30.258 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 
2012-05-04 08:34:30.274 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 
2012-05-04 08:34:30.290 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 
2012-05-04 08:34:30.306 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 
2012-05-04 08:34:30.322 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 
2012-05-04 08:34:30.338 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 
2012-05-04 08:34:30.354 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 
2012-05-04 08:34:30.371 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 
2012-05-04 08:34:30.387 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 
2012-05-04 08:34:30.403 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 
2012-05-04 08:34:30.419 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 
2012-05-04 08:34:30.439 TestUpdateArea[45745:707] {{0, 0}, {320, 460}} 
2012-05-04 08:34:30.457 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 

इसके अलावा, अगर मैं 10s या तो और फिर से शुरू से अधिक के लिए आगे बढ़ बंद करो, यह निश्चित रूप से यह होता है बहुत लगातार:

2012-05-04 08:34:33.305 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 
2012-05-04 08:34:33.321 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 
2012-05-04 08:35:00.202 TestUpdateArea[45745:707] {{0, 0}, {320, 460}} 
2012-05-04 08:35:00.221 TestUpdateArea[45745:707] {{0, 0}, {320, 460}} 
2012-05-04 08:35:00.234 TestUpdateArea[45745:707] {{0, 0}, {320, 460}} 
2012-05-04 08:35:00.251 TestUpdateArea[45745:707] {{10, 10}, {20, 20}} 
+0

मेरे मामले में, जब drawRect setNeedsDisplayInRect के बाद ** पहली बार ** कहा जाता है, रेक्ट पूर्ण सीमा (मत पूछो मेरी क्यों), किसी भी अगले फोन यह वास्तव में रेक्ट मैं setNeedsDisplayInRect में पैरामीटर के रूप में निर्दिष्ट है। क्या आपने स्पर्श को एक से अधिक बार परीक्षण किया था? –

+0

यह ज्यादातर डिवाइस पर सीधे होता है। लेकिन अगर आप अपनी अंगुली को चारों ओर ले जाते हैं और फिर लगभग 10 या 15 सेकंड तक प्रतीक्षा करते हैं, तो आप सिम्युलेटर पर ऐसा कर सकते हैं, फिर स्पर्श करें और फिर से जाएं। आईपैड 3 डिवाइस पर, यह तब भी होता है जब उंगली चलती है। बहुत परेशान :) – mprivat

+0

मैंने इसे थोड़ी देर पहले पोस्ट किया था (http://stackoverflow.com/questions/9299018/setneedsdisplayinrect-bug-in-ios5)। ऐसा लगता है कि केवल पहली कॉल पर ही था। मुझे कोई कारण/फिक्स नहीं मिला और बस चले गए क्योंकि मुझे प्रदर्शन अनुकूलन के उस स्तर की आवश्यकता नहीं थी।क्या आप rect == व्यू आकार के लिए परीक्षण कर सकते हैं और ड्रॉ नहीं कर सकते? शायद एक विकल्प नहीं है। –

उत्तर

5

चेक इस सेब document

उन्होंने कहा:

क्योंकि जिस तरह की है कि iPhone/iPod टच/iPad के upda यदि आप -setNeedsDisplayInRect: या -setNeedsDisplay: पर कॉल करते हैं, तो संपूर्ण दृश्य को फिर से खींचा जाएगा।

इसके अलावा

प्रत्येक UIView एक भी तत्व के रूप में व्यवहार किया जाता है। जब आप -setNeedsDisplayInRect: या -setNeedsDisplay: पर कॉल करके, भाग या पूरी तरह से रेड्रा का अनुरोध करते हैं, तो संपूर्ण दृश्य अपडेट के लिए चिह्नित किया जाएगा।

इसलिए मुझे लगता है कि आपको पूरे दृश्य के स्वतंत्र संदर्भ को अद्यतन करने के लिए उप-दृश्यों का उपयोग करने की आवश्यकता है।

+1

यह समझ में नहीं आता है। तब दो तरीकों को रखने में क्या बात होगी। और यह कभी-कभी क्यों काम करेगा? – mprivat

+0

मैंने कुछ पढ़ा जहां आईओएस 5 में एक बग है .. क्या आपने आईओएस 4 पर कोशिश की? –

+0

यह आईओएस 4 में बहुत कम हद तक करता है। – mprivat

0

मैं एक ऐसी ही मुद्दा है: अर्थात् setNeedsDisplayInRect के लिए एक कॉल के साथ एक UIView के केवल एक हिस्से को अद्यतन करने के लिए इच्छुक: जो मैं सही आकार का एक मान्य CGRect पारित (तोड़ अंक के साथ साबित कर दिया है, और लॉग्स)। आईओएस 4.2.1 के तहत (मेरे आईफोन 3 जी पर) यूआईवीव अपनी मूल छवि रखता है और केवल सीजीआरईटी द्वारा निर्दिष्ट हिस्से को अपडेट करता है, लेकिन आईओएस 5.1 (मेरे आईफोन 4 एस पर) के तहत पूरे यूआईवीव को पारदर्शी काला में फिर से खींचा जाता है (काला कैसे हो सकता है पारदर्शी मेरे बाहर है), सीजीआरईटी द्वारा निर्दिष्ट क्षेत्र के साथ सही ढंग से तैयार किया जा रहा है। ऐसा लगता है: ऐप्पल के हिस्से पर एक त्रुटि है कि वे setNeedsDisplayInRect को कार्यान्वित नहीं कर रहे हैं: सही ढंग से और इसे सेट करने के लिए बस इसे पास करने के लिए डिस्प्ले :; या यह एक दिलचस्प निर्णय था कि नया आईओएस वास्तविक स्क्रीन आर्किटेक्चर के साथ बातचीत कैसे करता है।किसी भी तरह से, ऐसा लगता है कि डेवलपर्स के समय या तो ग्राफिकल बदलाव होने पर हर यूआईवीयू को अपडेट करने की लागत पहननी होगी, या आईओएस का पता लगाने और आईओएस के आधार पर अलग-अलग स्क्रीन ड्राइंग कोड लागू करने के लिए उपयोग करना होगा।

मैंने UIView संपत्ति clearsContextBeforeDrawing (जो दस्तावेज़ीकरण के अनुसार लक्षित ड्राइंग ऑपरेशन की अनुमति देनी चाहिए) के साथ कुछ परीक्षण किया है, लेकिन परिणाम YES और NO दोनों के लिए समान हैं, इसलिए यह ड्राइंग कोड का कार्यान्वयन प्रतीत होता है ।

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

मैं इसमें खोदना जारी रखूंगा, लेकिन मुझे डर है कि जब तक ऐप्पल सेट नोड्सडिस्प्लेक्ट में परिवर्तन के लिए अपने तर्क का खुलासा नहीं करता है, या स्पष्ट बग को ठीक करता है, तो हम प्रत्येक ग्राफिकल के लिए UIView की संपूर्ण सामग्री को अपडेट करने पर विचार कर सकते हैं अद्यतन (जो संभावित रूप से बहुत महंगा हो सकता है)।

+0

यह मुझे डर था। मैंने ऐप्पल के साथ एक तकनीकी सहायता टिकट खोला और उन्होंने चुपचाप इसे बंद कर दिया और बिना किसी शब्द के टिकट टिकट को मेरे खाते में जमा कर दिया ... – mprivat

13

स्वीकृत उत्तर गलत है (या कम से कम भ्रामक)।

यहाँ setNeedsDisplayInRect का एक सरल कोड उदाहरण है: काम कर विज्ञापित के रूप में:

http://charcoaldesign.co.uk/resources/chalkboard.zip

मुझे लगता है कि एप्पल प्रलेखन तथ्य यह है कि iOS पर हर दृश्य समर्थन छवि एक ओपन बनावट में बदल जाती है समझाने के लिए कोशिश कर रहा है और पूरी स्क्रीन को हर फ्रेम को फिर से मिश्रित किया जाता है। इस सवाल से यह अलग है कि क्या आपके कोड को दृश्य के बैकिंग बनावट की संपूर्ण सामग्री को साफ़ करना और फिर से निकालना है या नहीं।

setNeedsDisplayInRect का उपयोग करके: आप उस सामग्री की महंगी पुनर्वितरण से बच सकते हैं जो फ्रेम के बीच नहीं बदलता है (जो मूल ग्राफिक्स का उपयोग करता है और हार्डवेयर त्वरित नहीं होता है)। पूरी स्क्रीन को फिर भी रेखांकित किया जाएगा, लेकिन इससे कोई फर्क नहीं पड़ता क्योंकि यह GPU द्वारा कोड को तेज करता है, ड्रॉरेक्ट में कोड के विपरीत:

0

मेरे पास बहुत सारे डिवाइस उपलब्ध नहीं हैं, लेकिन मेरे पास बहुत अच्छा है वैसे भी खबर! ऐसे व्यक्ति के रूप में जो वर्षों से आईओएस पर इस कार्यक्षमता की इच्छा रखते हैं, मैं जोर दे सकता हूं कि आईओएस 8.0 + इस कार्यक्षमता को लाता है। मैंने 8.0, 8.1, 8.2

के लिए दोनों सिम्युलेटर और डिवाइस पर कोशिश की है मैंने आईओएस 6 के बाद से यह कोशिश नहीं की है। तो मुझे यकीन नहीं है कि यह आईओएस 7 में उपलब्ध है या नहीं। शायद कोई और पुष्टि कर सकता है।

कृपया setNeedsDisplayInRect: दस्तावेज के रूप में काम करने के लिए अंतहीन रूप से उत्साह में मेरे साथ शामिल हों!