2012-09-20 9 views
37

साथ थ्रेड हटा मैं निम्न चेतावनी के साथ मुद्दों कर रहा हूँ:CoreAnimation चेतावनी अप्रतिबद्ध CATransaction

CoreAnimation: चेतावनी, अप्रतिबद्ध CATransaction साथ नष्ट कर दिया धागा; बैकट्रैस लॉग करने के लिए पर्यावरण में CA_DEBUG_TRANSACTIONS = 1 सेट करें।

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

मैं एक्सकोड 4.4.1 और ओएसएक्स 10.8.1 का उपयोग कर रहा हूं, हालांकि, जब मैं ओएसएक्स 10.7.4 पर एक्सकोड के उसी संस्करण का उपयोग करके कोड संकलित और चलाता हूं तो मुझे चेतावनी नहीं मिलती है और कोड अपेक्षित के रूप में चलता है।

CA_DEBUG_TRANSACTIONS = 1 पर्यावरण परिवर्तक सेट करना एनएससींट्रोल सेट से आने वाले बैकट्रैक को ऐपडिलेगेट में सक्षम संदेश दिखाता है।

उत्तर शायद मुझे चेहरे पर देख रहा है लेकिन शायद मेरे पास बहुत अधिक कॉफी है!

+3

मैं आज थोड़ा सा खेल रहा हूं। मुझे संदेह है कि मुद्दा यह है कि NSAperation UIA तत्वों को फिर से निकालने के साथ CoreAnimation समाप्त होने से पहले पूरा हो जाता है। बैकट्रैक ने मूल रूप से NSOperation से बुलाया जाने वाला तरीका दिखाया। मैंने NSOperation से NSNperation को लागू करने की कोशिश की ताकि गणना को पूरा किया जा सके, उम्मीद है कि एनएसओपरेशन कोरएनीमेशन को प्रभावित किए बिना जारी किया जा सकता है, हालांकि चेतावनी अभी भी होती है लेकिन इस बार स्रोत कोरफाउंडेशन है? – Milly

+1

दोनों मामलों में प्रोग्राम अपेक्षा के अनुसार काम करता प्रतीत होता है और चेतावनी केवल ओएस 10.8.1 या 10.8.2 – Milly

उत्तर

18

आपके संदेह सही हैं। यदि NSAperation CoreAnimation प्रदर्शन करने से पहले पूरा हो जाता है, तो आपको एक अच्छी चेतावनी मिलती है:

* कोरएनीमेशन: चेतावनी, असामान्य कैटर्रैक्शन के साथ हटाए गए थ्रेड; बैकट्रैसेस लॉग करने के लिए पर्यावरण में CA_DEBUG_TRANSACTIONS = 1 सेट करें। *

यह कुछ परिस्थितियों में भी हो सकता है जब एक कतार पर भेजा गया ब्लॉक CoreAnimation से कुछ काम ट्रिगर करता है और CoreAnimation समाप्त होने से पहले लौटाता है।

मैं जिस समाधान का उपयोग करता हूं वह सरल है: ब्लॉक या एनएसओपरेशन पर जो कोरएनीमेशन से काम करने का अनुरोध करता है, मैं जांचता हूं कि काम बाहर निकलने से पहले पूरा हो चुका है।

आपको सबूत-ऑफ-अवधारणा उदाहरण देने के लिए, यह एक प्रेषण कतार पर भेजा जाने वाला एक ब्लॉक है। चेतावनी से बचने के लिए, हम जांचते हैं कि कोरएनीमेशन बाहर निकलने से पहले किया जाता है।

dispatch_async(dispatch_get_main_queue(), ^{ 
    [self.delegate redrawSomething]; 
}); 

सामान्य तौर पर यह खराब फार्म वस्तुओं कॉल करने के लिए:

^{ 

    // 1. Creating a completion indicator 

    BOOL __block animationHasCompleted = NO; 

    // 2. Requesting core animation do do some work. Using animator for instance. 

    [NSAnimationContext runAnimationGroup:^(NSAnimationContext *context){ 
     [[object animator] perform-a-nice-animation]; 
    } completionHandler:^{ 
     animationHasCompleted = YES; 
    }]; 

    // 3. Doing other stuff… 

    … 

    // 4. Waiting for core animation to complete before exiting 

    while (animationHasCompleted == NO) 
    { 
     usleep(10000); 
    } 

} 
+3

पर चलने पर दिखाई देती है, यह सबसे अच्छा समाधान नहीं है क्योंकि यह अनावश्यक संसाधनों का उपभोग करता है। बेहतर समाधान के लिए नीचे देखें। विशेष रूप से, 'performSelectorOnMainThread का उपयोग करके: ऑब्जेक्ट: waitUntilDone: 'या' dispatch_async() '। – Dalmazio

+0

यह एक बुरा समाधान है, सभी एनिमेशन मुख्य धागे पर भेजा जाना चाहिए। – PPierson

+3

@PPierson असल में एनिमेशन मुख्य धागे को भेजे जाते हैं। मुझे नहीं लगता कि समाधान के साथ क्या गलत है। – Jean

24

मानक कोको मानदंड के अनुरूप, यहां सुझाए गए समाधान के मुख्य थ्रेड पर अपने कोर एनिमेशन काम को करने के, आसानी से GCD के साथ किया है संदर्भों में वे उम्मीद नहीं करते हैं, इसलिए अंगूठे का एक अच्छा नियम हमेशा बाहरी मॉड्यूल पर संदेश वितरित करते समय मुख्य धागे पर प्रेषित होता है।

कुछ ढांचे जैसे कोर स्थान-एक लॉग संदेश को उत्सर्जित करने के साथ अगर उन्हें मुख्य धागे के अलावा किसी भी संदर्भ से बुलाया जाता है। अन्य गुप्त एनिमेशन को उत्सर्जित करेंगे, जैसे कोर एनीमेशन के साथ आपका उदाहरण।

+1

ने कोशिश की और यह मेरे लिए काम नहीं किया – rbp

8

किसी भी यूआई ड्राइंग को सुनिश्चित करने के लिए एक अन्य तरीका मुख्य थ्रेड पर होता है, के रूप में Numist द्वारा वर्णित, विधि performSelectorOnMainThread:withObject:waitUntilDone: या वैकल्पिक रूप से performSelectorOnMainThread:withObject:waitUntilDone:modes:

- (void) someMethod 
{ 
    [...] 

    // Perform all drawing/UI updates on the main thread. 
    [self performSelectorOnMainThread:@selector(myCustomDrawing:) 
          withObject:myCustomData 
         waitUntilDone:YES]; 

    [...] 
} 

- (void) myCustomDrawing:(id)myCustomData 
{ 
    // Perform any drawing/UI updates here. 
} 


उपयोग कर रहा है के बीच अंतर पर एक संबंधित पोस्ट के लिए dispatch_async() और performSelectorOnMainThread:withObjects:waitUntilDone: देखें Whats the difference between performSelectorOnMainThread and dispatch_async on main queue?

+1

सरल और अच्छा समाधान :) –

संबंधित मुद्दे