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