Передача в пользовательский селектор реализации

Предположим, у меня есть два объективных класса с, LBFoo а также LBBar,

В LBFoo У меня есть метод, который выглядит так:

- (void)doSomethingWithFoo:(NSNumber*)anArgument
{
  if(anArgument.intValue > 2)
    [LBBar doSomethingWithLBBar];
  else
    [LBBar doSomethingElseWithLBBar];
}

Вместо этого я хотел бы передать реализацию LBBar это не было объявлено заранее. (Как в случае динамического переопределения существующего @selector в LBBar)

Я знаю что IMP тип существует, можно ли передать IMP к классу, чтобы изменить его реализацию селектора.

2 ответа

Решение

Вы можете использовать method_setImplementation(Method method, IMP imp) функция во время выполнения target-c.

если вы хотите установить метод экземпляра, он будет работать примерно так

method_setImplementation(class_getInstanceMethod([yourClass class], @selector(yourMethod)), yourIMP);

если вы хотите метод класса, просто используйте class_getClassMethod вместо class_getInstanceMethod, Аргументы должны быть одинаковыми.

это все, что нужно сделать. Обратите внимание, что IMP - просто указатель на пустую функцию, первые два параметра id self а также SEL _cmd

Вы, конечно, можете использовать функции времени выполнения, чтобы сделать что-то подобное *, но я бы предположил, что это именно та проблема, которую блоки были введены для решения. Они позволяют передавать часть исполняемого кода - ваш метод может фактически принять блок в качестве аргумента и запустить его.

Вот SSCCE:

#import <Foundation/Foundation.h>

typedef dispatch_block_t GenericBlock;

@interface Albatross : NSObject 
- (void)slapFace:(NSNumber *)n usingFish:(GenericBlock)block;
@end

@implementation Albatross

- (void)slapFace:(NSNumber *)n usingFish:(GenericBlock)block
{
    if( [n intValue] > 2 ){
        NSLog(@"Cabbage crates coming over the briny!");
    }
    else {
        block();    // Execute the block
    }
}

@end

int main(int argc, const char * argv[])
{

    @autoreleasepool {

        Albatross * p = [Albatross new];
        [p slapFace:[NSNumber numberWithInt:3] usingFish:^{
            NSLog(@"We'd like to see the dog kennels, please.");
        }];
         [p slapFace:[NSNumber numberWithInt:1] usingFish:^{
            NSLog(@"Lemon curry?");
        }];

    }
    return 0;
}

* Обратите внимание, что с помощью method_setImplementation() будет менять код, который используется каждый раз, когда метод вызывается в будущем из любого места - это постоянное изменение.

Другие вопросы по тегам