Objective-C 中的非虚拟方法
Non-virtual methods in Objective-C
我需要从类别中调用该方法的具体实现(即使它被重写)。可能吗? (以防万一:我知道,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" !!!
这可能会解决您的问题:
// 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" !!!
终于。确实方法调配有效
@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
您可以调整 Matt Gallagher's supersequent implementation approach 以找到您要调用的特定方法。
或者,您可以临时设置 class:
Class realClass = object_getClass(self);
Class fakeClass = [A class];
object_setClass(self, fakeClass);
[self foo];
object_setClass(self, realClass);
(我在 phone,所以不能 100% 确定语法,但这个想法应该可行。)
当然,您不必更改任何内容。
您可以获得一个函数指针,指向特定 class 上每个方法的实现:
A* receiver = …
IMP impOnA = class_getMethodImplementation( [A class], @selector( foo ));
((void (*)(id, SEL))impOnA)( receiver, @selector( foo ) ); // or whatever signature
我需要从类别中调用该方法的具体实现(即使它被重写)。可能吗? (以防万一:我知道,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" !!!
这可能会解决您的问题:
// 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" !!!
终于。确实方法调配有效
@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
您可以调整 Matt Gallagher's supersequent implementation approach 以找到您要调用的特定方法。
或者,您可以临时设置 class:
Class realClass = object_getClass(self);
Class fakeClass = [A class];
object_setClass(self, fakeClass);
[self foo];
object_setClass(self, realClass);
(我在 phone,所以不能 100% 确定语法,但这个想法应该可行。)
当然,您不必更改任何内容。
您可以获得一个函数指针,指向特定 class 上每个方法的实现:
A* receiver = …
IMP impOnA = class_getMethodImplementation( [A class], @selector( foo ));
((void (*)(id, SEL))impOnA)( receiver, @selector( foo ) ); // or whatever signature