为什么不能将super设置为NSInvocation的目标?
有没有其他方法可以做到这一点?
发布于 2012-03-23 08:55:10
虽然它看起来很像self,但super不是一个变量。这是一个关键字。例如,这是一个语法错误:
- (void)log {
NSLog(@"%@", super);
}“super”关键字只能用作消息的接收者,在这种情况下,意味着避免正常的多态调度,并调用属于所讨论代码的超类的方法。
如果你有这样的东西:
@interface Vehicle : NSObject
@end
@interface Car : Vehicle
@end
@implementation Vehicle
- (void)log {
NSLog(@"-[Vehicle log] invoked on an instance of %@", NSStringFromClass([self class]));
}
@end
@implementation Car
- (void)log {
NSLog(@"-[Vehicle log] invoked on an instance of %@", NSStringFromClass([self class]));
}
@end当接收方是Car实例时,这里有一种方法可以获取-Vehicle日志。
@implementation Car
- (void)log {
NSLog(@"-[Vehicle log] invoked on an instance of %@", NSStringFromClass([self class]));
}
- (void)runVehiclesLog {
[super log];
}
- (void)runInvocationThatTargetsVehicle {
SEL selector = @selector(runVehiclesLog);
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:selector]];
[invocation setTarget:self];
[invocation setSelector:selector];
[invocation invoke];
}
@end如果你不能编辑这个类,但仍然需要这样做,那么你可以使用+NSObject instanceMethodForSelector:来代替NSInvocation :如下所示:
typedef void (*MyVoidMethodWithNoArgs)(id receiver, SEL selector);
int main(int argc, const char * argv[]) {
@autoreleasepool {
Car *car = [[Car alloc] init];
MyVoidMethodWithNoArgs imp = (MyVoidMethodWithNoArgs)[Vehicle instanceMethodForSelector:@selector(log)];
imp(car, @selector(log));
}
return 0;
}在第二种情况下,您也可以避免动态分派,但是可以获得指向实现上面定义方法的c函数的指针。在调用之前,将instanceMethodForSelector:的结果强制转换为具有正确原型的函数是非常重要的。此外,选择器参数不是选择方法,而是将第二个隐藏参数填充到所有objective C函数中,选择器被调用。如果您在调用imp时传递了一个不同的选择器,代码仍会运行,但会违反约定。
发布于 2012-03-23 11:34:04
是的,有,但它使用私有API,永远不应该在发货应用程序中使用。
不久前Mike Ash discovered a private method on NSInvocation打电话给-invokeUsingIMP:他已经在一些things he has posted online中使用了这一点,这让他完成了一些非常巧妙的技巧。
您可以使用这个私有的-invokeUsingIMP:方法来调用IMP,方法是找出与super调用相对应的IMP,然后将该IMP作为参数传递给-invokeUsingIMP:。
由于这是私有API,您不应该真正使用它,因此我不打算发布演示如何做到这一点的代码示例。
但是,是的,这是可能的。
发布于 2012-03-23 07:21:56
super指向与self完全相同的对象--请尝试记录self和super的值,并亲自查看。不同之处在于,super使方法搜索从父类开始。
因此,如果您将super作为对象引用传递(如果编译器允许您这样做的话),它基本上与传递self相同。
https://stackoverflow.com/questions/9831914
复制相似问题