首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSInvocation和super

NSInvocation和super
EN

Stack Overflow用户
提问于 2012-03-23 07:12:22
回答 4查看 2K关注 0票数 2

为什么不能将super设置为NSInvocation的目标?

有没有其他方法可以做到这一点?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-03-23 08:55:10

虽然它看起来很像self,但super不是一个变量。这是一个关键字。例如,这是一个语法错误:

代码语言:javascript
复制
- (void)log {
    NSLog(@"%@", super);
}

“super”关键字只能用作消息的接收者,在这种情况下,意味着避免正常的多态调度,并调用属于所讨论代码的超类的方法。

如果你有这样的东西:

代码语言:javascript
复制
@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日志。

代码语言:javascript
复制
@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 :如下所示:

代码语言:javascript
复制
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时传递了一个不同的选择器,代码仍会运行,但会违反约定。

票数 6
EN

Stack Overflow用户

发布于 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,您不应该真正使用它,因此我不打算发布演示如何做到这一点的代码示例。

但是,是的,这是可能的。

票数 5
EN

Stack Overflow用户

发布于 2012-03-23 07:21:56

super指向与self完全相同的对象--请尝试记录selfsuper的值,并亲自查看。不同之处在于,super使方法搜索从父类开始。

因此,如果您将super作为对象引用传递(如果编译器允许您这样做的话),它基本上与传递self相同。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9831914

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档