假设我有两个Objective-c类,LBFoo
和LBBar
。
在LBFoo
我的方法如下:
- (void)doSomethingWithFoo:(NSNumber*)anArgument
{
if(anArgument.intValue > 2)
[LBBar doSomethingWithLBBar];
else
[LBBar doSomethingElseWithLBBar];
}
我想要做的是将实现传递给未提前声明的LBBar
。 (如动态覆盖LBBar
中的现有@selector)
我知道存在IMP
类型,是否可以将IMP
传递给类以更改其选择器实现。
答案 0 :(得分:2)
您可以使用objective-c runtime中的method_setImplementation(Method method, IMP imp)
功能。
如果你想设置一个实例方法,它会像这样工作
method_setImplementation(class_getInstanceMethod([yourClass class], @selector(yourMethod)), yourIMP);
如果你想要一个类方法,只需使用class_getClassMethod
而不是class_getInstanceMethod
。论点应该是一样的。
这就是它的全部。请注意,IMP只是一个void函数指针,前两个参数为id self
和SEL _cmd
答案 1 :(得分:1)
你当然可以使用运行时函数来做这样的事情,*但我建议完全引入Blocks要解决的问题。它们允许您传递一大块可执行代码 - 您的方法实际上可以接受Block作为参数并运行它。
这是一个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()
将改变以后每次从任何地方调用该方法时使用的代码 - 这是持续的更改。