Objective C 通过 OOP 块作为参数

发布于 2025-01-07 15:14:09 字数 1171 浏览 0 评论 0原文

我创建了一个名为“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;
    }
}

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

然后我制作了几个图块,如下所示:

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

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

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

音盲 2025-01-14 15:14:09

块在堆栈上分配。

在这种情况下,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 has 一篇关于块和 ARC 的文章非常值得一读。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文