static variables inside Objective-C blocks?

℡╲_俬逩灬. 提交于 2019-12-04 07:13:23

Make the block return a value and then decide whether or not to remove the block from the dictionary.

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

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

Let's test the static variable

@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];
}

This outputs

#=> 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

How do we solve the problem? I would probably remove the object from the dictionary once it had been executed like this

- (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];
}

Your comment

So far so good, only that If I pop the brochure from the navigation controller (aka calls dealloc on the brochure) and then push it in again, the static bool is still set.

seems to imply you want a BOOL member variable on the pushed view controllers... If that's correct you can achieve this using objc_setAssociatedObject().

I might add a category to UIViewController to achieve this:

@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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!