所以我所拥有的是一个类层次结构如下:
@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
,但这不起作用。
答案 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));