0

我目前正在尝试使用forwardInvocation但遇到了一些麻烦。我想将ClassA一组有限方法的调用转发到ClassB存储为 my 中的属性的另一个实例 (of ) ClassA,但我还希望在 my 中有一个后备方法ClassA,如果方法未在ClassB.

不幸的是,我发现无论在什么方法上实现ClassBClassA方法总是被调用!

我实现这一点的方式如下所示。任何人都可以就我哪里出错提供任何建议吗?

static NSSet *forwardMessages;

@implementation ClassA

@synthesize classBInstance;

- (id) initWithDelegate:(id)delegate {
    self = [super init];
    classBInstance = delegate;
    return self;
}  

+ (void) initialize {
    if (self == [ClassA class]) {
        forwardMessages = [[NSSet alloc] initWithObjects: 
                       @"doSomething",
                       @"doSomethingElse",
                       @"anotherThing",
                       @"yetMoreThings",
                       nil];

- (BOOL) respondsToSelector:(SEL)aSelector {
    return [super respondsToSelector:aSelector] || [self isHandledByDelegate:aSelector];
}

- (BOOL) isHandledByDelegate:(SEL)aSelector {
    return [forwardMessages containsObject:NSStringFromSelector(aSelector)] &&
           [classBInstance respondsToSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    BOOL forwardThis = [self isHandledByDelegate: [anInvocation selector]];

    if (forwardThis) {
        [anInvocation invokeWithTarget:classBInstance];
    } else {
        [super forwardInvocation:anInvocation];
    }
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    Class handlingClass = [self isHandledByDelegate:aSelector]? [classBInstance class]:[self class];
    return [handlingClass instanceMethodSignatureForSelector:aSelector];
}

- (void) doSomething {
    // this should be forwarded to classBInstance but is always called!
}
4

1 回答 1

1

-forwardInvocation仅当正在调用的类上不存在具有该签名的方法时,才由方法调度调用。如果您只是尝试在委托具有这些方法的情况下调用委托上的方法,但是您想在类中使用默认实现,否则您不需要使用-forwardInvocation,只需使用覆盖委托模式即可。

- (void)doSomething {
    if ([delegate respondsToSelector: @selector(doSomething)]) {
        [delegate doSomething];
        return;
    }
    // ... default behavior
}

如果你真的想使用一个复杂的形式,它有一个要覆盖的方法列表等,你可能最终会使用 NSProxy 的子类来前端它并确定要调用哪个类,但是这似乎过于复杂,除非您无法访问您尝试填充的类。

于 2013-06-18T09:57:49.900 回答