2012-04-22 17 views
5

मैं कुछ कोरएनीमेशन सामान पर काम कर रहा हूं। कुछ दृश्य नियंत्रकों के साथ एक नेविगेशन नियंत्रक। और दृश्य नियंत्रकों के पास "ब्रोशर" के विभिन्न "पृष्ठों" के लिए UISCrollViews हैं। प्रत्येक पृष्ठ पर, कुछ एनीमेशन हो सकता है जो उपयोगकर्ता उस पृष्ठ पर फ़्लिप करते समय ट्रिगर हो जाता है।स्थैतिक चर?

मैं इस तरह कुछ कोशिश कर रहा था (एक शॉट एनीमेशन के लिए)।

void (^animationBlock)() = 
    ^{ 
    static bool alreadyTriggered = NO; 
    if(alreadyTriggered) 
     return; 

    [CATransaction begin]; 
    [CATransaction setCompletionBlock: 
    ^{ 
     alreadyTriggered = YES; 
    }]; 

    // Do me some animations... 

    [CATransaction commit]; 
    }; 

    NSMutableDictionary* pageBlocks = [[NSMutableDictionary alloc] init]; 
    [pageBlocks setObject:[animationBlock copy] forKey:<animation's name>]; 
    [self.animationBlocks setObject:pageBlocks forKey:<some page number>]; 

    [pageBlocks release]; 
    [animationBlock release]; 

"एनीमेशन का नाम" और "कुछ पृष्ठ संख्या" स्पष्टीकरण के लिए प्लेसहोल्डर हैं (वे मनमाने ढंग से NSString शाब्दिक हैं)।

और कोड है कि इन एनिमेशन से चलाता है:

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView 
{ 
    int pageNumber = floor(self.scrollView.contentOffset.x/self.scrollView.frame.size.width); 
    NSMutableDictionary* pageBLocks = [self.animationBlocks objectForKey:[NSString stringWithFormat:@"page%i",pageNumber]]; 
    [CATransaction begin]; 
    for(id key in pageBLocks) 
    ((void (^)())[pageBLocks objectForKey:key])(); 
    [CATransaction commit]; 
} 

अब तक तो अच्छा है, केवल कि मैं नेविगेशन नियंत्रक से विवरणिका पॉप हैं (उर्फ विवरणिका पर dealloc कॉल) और उसे फिर से धक्का में , स्थिर बूल अभी भी सेट है।

मेरे विचार:

- मैं ब्लॉक बनाए रखने कर रहा हूँ? मुझे नहीं पता .. मैं इसे (प्रतिलिपि के साथ) शब्दकोश में जोड़ने के बाद रिलीज कर रहा हूं और ब्रोशर की डेलोक विधि शब्दकोष को रिलीज़ करता है।

- क्या मैं कहीं स्थिर बूल की एक और प्रतिलिपि रख रहा हूं? मेरा पहला बूल आवंटित किया जाता है जब मैं ब्लॉक को विधि के दायरे में स्थिर के रूप में घोषित करता हूं .. अच्छी तरह से उद्देश्य-सी की सक्रियण रिकॉर्ड योजना पर निर्भर करता है जिसे मैंने नहीं देखा है। लेकिन ऐसा मानते हुए, popViewcOntroller पर ऑब्जेक्ट जारी करते समय वह प्रतिलिपि समाप्त हो गई है। और जब इसे शब्दकोश में जोड़ते समय ब्लॉक पर आक्रमणकारी प्रतिलिपि से इसकी एक और प्रतिलिपि जारी की जानी चाहिए तो शब्दकोश को मार दिया जाना चाहिए?

क्या मैं पूरी ब्रोशर ऑब्जेक्ट को स्वयं बनाए रख रहा हूं? मुझे इसे पूरी तरह से ऐप्पल दस्तावेज़ से नहीं मिला, लेकिन वे कहते हैं कि यदि मैं संदर्भ द्वारा एक आवृत्ति चर का उपयोग करता हूं तो मैं स्वयं को बनाए रखता हूं। मैंने ब्लॉक के अंदर से खुद को रिहा करने की कोशिश की और सब ठीक चल रहा है ...?

+0

मुझे नहीं लगता कि आप 'मिश्रण चाहिए साथ' Block_release() '[ब्लाकों प्रोग्रामिंग विषय] (http copy' है: // डेवलपर। apple.com/library/ios/#documentation/Cocoa/Conceptual/Blocks/Articles/bxUsing.html#//apple_ref/doc/uid/TP40007502-CH5-SW1) –

+0

एह? ब्लॉक को ढेर से ढेर – SaldaVonSchwartz

+0

पर ले जाने का तरीका यह है कि दस्तावेज़ आपको सुझाव देता है कि आपको ब्लॉक_रली() 'और' बैलेंस कॉपी या रिहाई के साथ बनाए रखना (या ऑटोरेलीज़) ' –

उत्तर

1

ब्लॉक को एक मान वापस करें और फिर तय करें कि शब्दकोश से ब्लॉक को निकालना है या नहीं।

// ... 
    BOOL shouldRemove = block(); 

    if (shouldRemove) { 
     [pageBlocks removeObjectForKey:key]; 
    } 
// ... 

के स्थिर चर जांचते हैं

@interface TestClass : NSObject 
@end 

@implementation TestClass 

- (void(^)(void))block; 
{ 
    return [[^{ 

     static BOOL staticBOOL = NO; 

     NSLog(@"%d", staticBOOL); 

     staticBOOL = YES; 

    } copy] autorelease]; 
} 

@end 

int main(int argc, char *argv[]) { 
    NSAutoreleasePool *p = [[NSAutoreleasePool alloc] init]; 

    TestClass *test1 = [[TestClass alloc] init]; 
    test1.block(); 
    test1.block(); 

    TestClass *test2 = [[TestClass alloc] init]; 
    test2.block(); 
    test2.block(); 

    [p release]; 
} 

यह

#=> 2012-04-23 00:43:38.501 Untitled[8380:707] 0 
#=> 2012-04-23 00:43:38.503 Untitled[8380:707] 1 
#=> 2012-04-23 00:43:38.503 Untitled[8380:707] 1 
#=> 2012-04-23 00:43:38.504 Untitled[8380:707] 1 

आउटपुट हम इस समस्या को कैसे हल करते हैं? मैं शायद शब्दकोश से वस्तु हटा एक बार यह इस

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView; 
{ 
    NSInteger pageNumber = floor(self.scrollView.contentOffset.x/self.scrollView.frame.size.width); 
    NSMutableDictionary *pageBlocks = [self.animationBlocks objectForKey:[NSString stringWithFormat:@"page%i", pageNumber]]; 

    [CATransaction begin]; 

    for (id key in [pageBlocks copy]) { 
     void (^block)(void) = [pageBlocks objectForKey:key]; 
     if (block) { 
      block(); 
     } 
     [pageBlocks removeObjectForKey:key]; 
    } 

    [CATransaction commit]; 
} 
+0

सही मैंने इसके बारे में सोचा, लेकिन समस्या यह नहीं है कि सभी एनीमेशन ब्लॉक "एक शॉट" हैं। कुछ को वास्तव में हर बार फिर से निष्पादित करना चाहिए और शब्दकोश से हटाया नहीं जाना चाहिए। तो मुझे ब्लॉक को खुद को एक शॉट में सेट करने के लिए एक तरीका चाहिए या नहीं। – SaldaVonSchwartz

+0

दो अलग-अलग शब्दकोश? –

+0

ehhh ... मेरा मतलब है ... लेकिन यह पर्याप्त सुरुचिपूर्ण नहीं है (कम से कम इस परियोजना के दायरे में मेरे स्वाद के लिए, कोई अपराध नहीं)। मेरा विचार था कि ब्लॉक एक थ्रेड की तरह व्यवहार करता है और उसके पास इसका खुद का ढेर होना चाहिए .. इसलिए आंतरिक कॉल को पूरे कॉल में रखने के लिए एक तरीका होना चाहिए – SaldaVonSchwartz

0

आपकी टिप्पणी की तरह मार डाला गया था

अब तक तो अच्छा है, केवल कि मैं नेविगेशन नियंत्रक से विवरणिका पॉप हैं (उर्फ ब्रोशर पर डेलोक कॉल करता है) और फिर इसे में फिर से दबाएं, स्थिर बूल अभी भी सेट है।

आप धक्का दिया दृश्य नियंत्रकों पर एक BOOL सदस्य चर चाहते मतलब लगता है ... अगर वह सही है आप objc_setAssociatedObject() का उपयोग कर इस लक्ष्य को हासिल कर सकते हैं।

मैं UIViewController के लिए कोई श्रेणी जोड़ने के इस लक्ष्य को हासिल करने के लिए हो सकता है:

@interface UIViewController (OneShotAnimation) 
@property (nonatomic) BOOL animationHasBeenPlayed ; 
@end 

@implementation UIViewController (OneShotAnimation) 

-(void)setAnimationHasBeenPlayed:(BOOL)b 
{ 
    objc_setAssociatedObject(self, @"animationHasBeenPlayed", [ NSNumber numberWithBool:b ], OBJC_ASSOCIATION_RETAIN_NONATOMIC) ; 
} 

-(BOOL)animationHasBeenPlayed 
{ 
    return [ objc_getAssociatedObject(self, @"animationHasBeenPlayed") boolValue ] ; 
} 

@end 
+0

ओह में पूछूंगा .. लेकिन ब्रोशर आपके धक्का दृश्य नियंत्रक है, और इसे हटा दिया जा रहा है ... इसलिए इससे – nielsbot

+0

की सहायता नहीं होगी ठीक है ... जैसे मैंने पॉल को बताया, बूल व्यू कंट्रोलर के लिए नहीं है। बूल को कंट्रोलर्स के डिक्शनरी में रखे गए कई ब्लॉक के लिए एक तरीका के रूप में जाना जाता था, अगर उन्हें फिर से खेलना चाहिए या नहीं। इसे ब्लॉक नियंत्रक के बावजूद ब्लॉक के "आंतरिक राज्य" का हिस्सा माना जाता है, जिसे वे अंदर घोषित किया जाता है। तो एक ब्लॉक प्रति ब्लॉक – SaldaVonSchwartz

+0

लगता है जैसे आपके ब्लॉक को सदस्य चर की आवश्यकता है। आप अभी भी 'objc_setAssociatedObject' – nielsbot

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