0

i make a class called "Tile" which is a square, and the passed block will get called when touched.

-(id) initWithRect: (CGRect) r color: (ccColor4B) c block: (void (^) (void)) blk {
    if ((self = [super init])) {
        rect = r;
        color = c;
        block = blk;
        tile = [CCLayerColor layerWithColor:color width:rect.size.width height:rect.size.height];
        tile.position = ccp(rect.origin.x, rect.origin.y);
        [self addChild: tile];
        self.isTouchEnabled = YES;
    }
    return self;
}

//rect is the square, i use CCLayerColor to represent the square.

-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
    CGPoint touchLocation = [Helper locationFromTouch: touch];
    if (CGRectContainsPoint(rect, touchLocation)) {
        block();
        [tile setColor:ccGRAY];
        return YES;

    }
    else {
        return NO;
    }
}

//when touched, just call the block.

then i make a couple of Tiles as follows:

Tile* aTile = [Tile tileWithMidPos:ccp(512, 500) width:300 height:200 color:ccc4(250, 250, 250, 250) block:^{
            [Helper playEffectButtonClicked];
        }];

but all the tiles actually execute the block that is passed by the last tile. what is the problem here? (every tile is an object, so they should call their own block)

1 Answer 1

2

Blocks are allocated on the stack.

In this case the Tile class should make a copy of the blk argument:

-(id) initWithRect: (CGRect) r color: (ccColor4B) c block: (void (^) (void)) blk {
    if ((self = [super init])) {
        rect = r;
        color = c;
        block = [blk copy];
        tile = [CCLayerColor layerWithColor:color width:rect.size.width height:rect.size.height];
        tile.position = ccp(rect.origin.x, rect.origin.y);
        [self addChild: tile];
        self.isTouchEnabled = YES;
    }
    return self;
}

- (void)dealloc {
    [block release];
    [super dealloc];
}

If you are using ARC, you won't need to worry about memory management (copy and release) if they are passed to methods with block parameters. If you pass stack allocated blocks to objects with id parameters, you must still copy:

[myArray addObject:[^{ // some block } copy]];

Mike Ash has an article well worth reading regarding blocks and ARC.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.