我需要从类别中调用方法的具体实现(即使它已被覆盖)。可能吗? (以防万一:我知道,Objective-C中的所有方法都是虚拟的。)
// class A
@interface A
- (void)foo;
@end
@implementation A
- (void)foo
{
NSLog(@"initial foo");
}
@end
// subclass of A
@interface A1: A
@end
@implementation A1
- (void)foo
{
NSLog(@"overridden foo");
}
@end
// category to A
@interface A (Category)
- (void)bar;
@end
@impletemtation A (Category)
- (void)bar
{
[self foo]; // probably, I should specify here what exactly must be self
// but I don't know how
}
@end
/////////////////////////////////////////////////////////////////
A1 *a = [[A1 alloc] init];
[a bar]; // now the "overridden foo" string will be printed
// my goal is to print "initial foo" !!!
答案 0 :(得分:3)
当然,你不必改变任何东西。
您可以获取指向特定类上每个方法的实现的函数指针:
A* receiver = …
IMP impOnA = class_getMethodImplementation( [A class], @selector( foo ));
((void (*)(id, SEL))impOnA)( receiver, @selector( foo ) ); // or whatever signature
答案 1 :(得分:2)
您可以调整Matt Gallagher's supersequent implementation approach以查找要调用的特定方法。
或者,您可以暂时设置该类:
Class realClass = object_getClass(self);
Class fakeClass = [A class];
object_setClass(self, fakeClass);
[self foo];
object_setClass(self, realClass);
(我在手机上,所以不是100%肯定语法,但这个想法应该有用。)
答案 2 :(得分:0)
最后。确实是方法swizzing工作
@implementation A (Category)
- (void)quux
{
NSLog(@"quux");
}
- (void)bar
{
Class class = [A class];
SEL originalSelector = @selector(foo);
SEL swizzledSelector = @selector(quux);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
[self quux];
method_exchangeImplementations(originalMethod, swizzledMethod);
}
@end
答案 3 :(得分:-1)
这可以解决您的问题:
// class A
@interface A
- (void)foo;
@end
@implementation A
- (void)foo
{
[self fooImpl];
}
- (void)fooImpl
{
NSLog(@"initial foo");
}
@end
// subclass of A
@interface A1: A
@end
@implementation A1
- (void)foo
{
NSLog(@"overridden foo");
}
@end
// category to A
@interface A (Category)
- (void)bar;
@end
@impletemtation A (Category)
- (void)bar
{
[self fooImpl]; // probably, I should specify here what exactly must be self
// but I don't know how
}
@end
/////////////////////////////////////////////////////////////////
A1 *a = [[A1 alloc] init];
[a bar]; // now the "overridden foo" string will be printed
// my goal is to print "initial foo" !!!