Objective-C中的非虚方法

时间:2016-06-12 14:48:35

标签: objective-c virtual-functions

我需要从类别中调用方法的具体实现(即使它已被覆盖)。可能吗? (以防万一:我知道,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" !!!

4 个答案:

答案 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" !!!