Запоминание executeSelector: для дальнейшего использования в Objective-C - PullRequest
3 голосов
/ 29 января 2012

В физическом цикле 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:.Есть ли лучший способ обойти это?

РЕДАКТИРОВАТЬ:

Я попробовал оба способа и нашел блоки, чтобы быть проще.Я использую протокол, поэтому я не был уверен, как с этим справиться (он всегда будет возвращать ноль 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];

Ответы [ 2 ]

3 голосов
/ 29 января 2012

Возможно, NSInvocation?


2 голосов
/ 29 января 2012

Как насчет блоков?

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

Это с ARC; без ARC вы, вероятно, должны добавить copy и autorelease при добавлении блоков в массив.

...