记住performSelector: 以便稍后在 Objective-C 中使用

发布于 2024-12-29 09:01:57 字数 1458 浏览 0 评论 0原文

在我的游戏的 box2d 物理循环(该步骤)中,我必须调用以下块:

if ([objectA conformsToProtocol:@protocol(FMCollisionProtocol)]) {
    [objectA performSelector:@selector(collideWith:) withObject:objectB];
}
if ([objectB conformsToProtocol:@protocol(FMCollisionProtocol)]) {
    [objectB performSelector:@selector(collideWith:) withObject:objectA];
}

问题是 collideWith: 可能会改变我的物理对象,而这在该步骤中是不允许的。一旦该步骤完成,物理对象就可以再次自由更改。我需要某种方法来记住该块的目标、选择器和对象参数以供以后使用。一种选择是使用如下结构:

typedef struct {
    id target;
    SEL selector;
    id object;
} FMCallback;

并将它们存储在数组中。完成步骤后,我会分析该数组并调用 performSelector:。有更好的方法解决这个问题吗?

编辑:

我尝试了两种方法,发现块更简单。我正在使用一个协议,所以我不确定如何处理这个问题(它总是返回一个 nil NSMethodSignature):

NSMethodSignature *sig = [FMObject instanceMethodSignatureForSelector:@selector(collideWith:)];
NSInvocation *invoc = [NSInvocation invocationWithMethodSignature:sig];
invoc.target = objectB;
invoc.selector = @selector(collideWith:);
[invoc setArgument:objectA atIndex:2];
[Presenter.physics.callbacks addObject:invoc];

它也比我希望的要长。经过一番阅读后,这些块工作得很好:

// In the collision
[Presenter.physics.callbacks addObject: Block_copy(^{
    [(id)objectB collideWith:objectA];
})];

// After the step
for (id collision in callbacks_) {
    ((dispatch_block_t)collision)();
    Block_release(collision);
}
[callbacks_ removeAllObjects];

In the box2d physics loop of my game (the step), I must call the following block:

if ([objectA conformsToProtocol:@protocol(FMCollisionProtocol)]) {
    [objectA performSelector:@selector(collideWith:) withObject:objectB];
}
if ([objectB conformsToProtocol:@protocol(FMCollisionProtocol)]) {
    [objectB performSelector:@selector(collideWith:) withObject:objectA];
}

The problem is that collideWith: may alter my physics object and this isn't allowed during the step. Once the step is finished, the physics objects are free to be altered once more. I need some way to remember the target, selector and object paramater of this block for later use. One option would be to use a struct like this:

typedef struct {
    id target;
    SEL selector;
    id object;
} FMCallback;

And store these in an array. Once I've finished my step, I then analyse this array and call performSelector:. Is there a better way around this?

EDIT:

I tried both ways and found blocks to be simpler. I'm using a protocol, so I was unsure how to handle this (it would always return a nil NSMethodSignature):

NSMethodSignature *sig = [FMObject instanceMethodSignatureForSelector:@selector(collideWith:)];
NSInvocation *invoc = [NSInvocation invocationWithMethodSignature:sig];
invoc.target = objectB;
invoc.selector = @selector(collideWith:);
[invoc setArgument:objectA atIndex:2];
[Presenter.physics.callbacks addObject:invoc];

It was also longer than I would have hoped. The blocks worked fine after some reading:

// In the collision
[Presenter.physics.callbacks addObject: Block_copy(^{
    [(id)objectB collideWith:objectA];
})];

// After the step
for (id collision in callbacks_) {
    ((dispatch_block_t)collision)();
    Block_release(collision);
}
[callbacks_ removeAllObjects];

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

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

发布评论

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

评论(2

乜一 2025-01-05 09:01:57

也许是一个NSInspiration


Perhaps an NSInvocation?


寻梦旅人 2025-01-05 09:01:57

块怎么样?

NSMutableArray *collisions = [NSMutableArray array];
…
[collisions addObject:^{
    [objectA collideWith:objectB];
}];
…
for (id collision in collisions)
    ((dispatch_block_t)collision)();

这是 ARC 的情况;如果没有 ARC,您可能应该在将块添加到数组时添加 copyautorelease

How about blocks?

NSMutableArray *collisions = [NSMutableArray array];
…
[collisions addObject:^{
    [objectA collideWith:objectB];
}];
…
for (id collision in collisions)
    ((dispatch_block_t)collision)();

This is with ARC; without ARC you should probably add a copy and autorelease when adding the blocks to the array.

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