在目标c中调用super.super上的方法?

时间:2014-10-02 13:59:25

标签: objective-c

所以我所拥有的是一个类层次结构如下:

@interface MyClass : ParentClass

-(void)myMethod
{
    [super myMethod];
    // some specific operation
}

@end

@interface ParentClass : ParentParentClass

-(void)myMethod
{
    [super myMethod];
    // some specific operation
}

@end

@interface ParentParentClass : ParentParentParentClass

-(void)myMethod
{
    [super myMethod];
    // some specific operation
}

@end

现在让我们说,在MyClass中,我想避免拨打ParentClass的{​​{1}},而是要调用myMethod中的myMethod }}

我该怎么做?

我已经尝试过投射ParentParentClass,但这不起作用。

4 个答案:

答案 0 :(得分:5)

你应该可以这样做:

Method method = class_getInstanceMethod([ParentParentClass class], @selector(myMethod));
IMP imp = method_getImplementation(method);
((void (*)(id, SEL))imp)(self, @selector(myMethod)); // cast the function to the correct signature

您可能需要#import <objc/runtime.h>才能进行编译。

这将获得该方法在编译时转换为的实际C函数,然后可以调用该函数。当Objective-C编译器编译你的代码时,所有方法都被转换为普通的C函数,其中self作为第一个参数,而_cmd,当前方法的选择器作为第二个参数,其次通过Objective-C方法采用的所有其他参数。 class_getInstanceMethod获取给定方法的运行时表示(包括各种元数据),method_getImplementation从该方法获取普通C函数指针。

如果查看Objective-C运行时标头,您会看到IMP类型被定义为typedef id (*IMP)(void);,因此您需要将其转换为方法的实际类型实现函数,它将是(return_type (*)(id, SEL, method_arguments_in_order)) - 函数将self和方法选择器作为前两个参数,然后是ObjC方法参数。

因此,一旦你有了标准的C函数指针,就可以像调用函数一样调用它。

我不会把这种方法称为 hacky ,但它肯定是非标准的,正如需要使用底层运行时方法直接实现你想要的。在设计,可靠性和有意义方面,我肯定会认为这是一个更好的解决方案,而不是在称为超类的超类中添加桥接方法。方法

答案 1 :(得分:0)

super不是一个对象,它是一个特殊的关键字,告诉编译器发出对objc_msgSendSuper而不是objc_msgSend的调用。

由于没有objc_msgSendSuperSuper这样的功能,你无法做到。

您必须依赖具有不同选择器的方法。

答案 2 :(得分:0)

这是一个非常糟糕的做法,
无论如何,如果你需要这样做,你需要建立一个调用

的桥接方法
@interface MyClass : ParentClass

-(void)myMethod
{
    // INVOKE BRIDGE
    [super myMethodSuperBridge];
    // some specific operation
}

@end

@interface ParentClass : ParentParentClass

-(void)myMethod
{
    [super myMethod];
    // some specific operation
}

- (void)myMethodSuperBridge
{
    [super myMethod];
}
@end

@interface ParentParentClass : ParentParentParentClass

-(void)myMethod
{
    [super myMethod];
    // some specific operation
}

答案 3 :(得分:0)

你可以这样做

(void(*)(struct objc_super *, SEL, id))objc_msgSendSuper)(&(struct objc_super){self, [[self superclass] superclass]}, @selector(myMethod));

也许你想调用super.super.super方法,你可以这样做

(void(*)(struct objc_super *, SEL, id))objc_msgSendSuper)(&(struct objc_super){self, [[[self superclass] superclass] superclass]}, @selector(myMethod));