Передача в пользовательский селектор реализации
Предположим, у меня есть два объективных класса с, 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()
будет менять код, который используется каждый раз, когда метод вызывается в будущем из любого места - это постоянное изменение.