objective c传递块作为参数与OOP

时间:2012-02-20 11:45:00

标签: iphone objective-c ios block

我创建了一个名为“Tile”的类,它是一个正方形,触摸时会调用传递的块。

-(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是正方形,我使用CCLayerColor来表示正方形。

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

//触摸时,只需调用该块即可。

然后我按照以下方式制作几个Tiles:

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

但是所有的tile实际上都执行了最后一个tile传递的块。 这里有什么问题? (每个tile都是一个对象,所以他们应该调用自己的块)

1 个答案:

答案 0 :(得分:2)

块在堆栈上分配。

在这种情况下,Tile类应该复制blk参数:

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

如果您使用ARC,如果将它们传递给具有块参数的方法,则无需担心内存管理(复制和释放)。如果将堆栈分配的块传递给具有id参数的对象,则仍必须复制:

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

Mike Ash an article非常值得阅读有关积木和ARC的信息。