iOS: NSProxy не может перехватить метод, вызываемый внутри самого класса

Я использую NSProxy, чтобы смоделировать класс, и хочу перехватить все вызовы класса. Но подключаются только методы, вызываемые вне класса, без методов, вызываемых внутри класса. Ниже приведено что-то вроде моего кода:

В моем AppDelegate.mTBClassMock является подклассом NSProxy

TBClassMock *mock = [[TBClassMock alloc] init];
TBTestClass *foo = [[TBTestClass alloc] init];
mock.target = foo;

foo = mock;
[foo outsideCalled];

В моем TBTestClass.m

- (void)outsideCalled
{
    [self insideCalled];
}

- (void)insideCalled
{

}

В моем TBClassMock.m

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
    NSLog(@"Signature: %@", NSStringFromSelector(selector));
    return [self.target methodSignatureForSelector:selector];
}

-(void)forwardInvocation:(NSInvocation*)anInvocation
{
    //... Do other things

    [anInvocation invokeWithTarget:self.target];
}

Тогда я могу войти вызов [foo outsideCalled], но не могу войти в вызов [self insideCalled],

Я стремлюсь сделать что-то во всех вызовах класса в //... Do other thingsи этот путь кажется неудачным. Любые объяснения об этом и любом другом методе для выполнения моего требования? Я просто не хочу ругать все методы класса, используя method_exchangeImplementations как мне кажется это слишком привередливый и не очень хороший способ.

1 ответ

Я полагаю, вы неправильно поняли концепцию NSProxy. NSProxy означает класс, это не что-то само по себе. Предполагается, что NSProxy будет использоваться следующим образом: вы просто вызываете все методы на прокси, как если бы это был класс, за который он выступает.

В вашем коде вместо:

foo = mock;
[foo outsideCalled];

Делать:

[mock outsideCalled];

Это весь мой код:

#import <Foundation/Foundation.h>

@interface TBTestClass : NSObject

- (void)outsideCalled;
- (void)insideCalled;

@end

@implementation TBTestClass
- (void)outsideCalled;
{
    NSLog(@"TBTestClass:outsideCalled");
    [self insideCalled];
}
- (void)insideCalled;
{
    NSLog(@"TBTestClass:insideCalled");
}
@end


@interface TBClassMock : NSProxy
@property (retain) id target;
@end

@implementation TBClassMock

@synthesize target;

- (void)dealloc
{
    self.target = nil;
}

- (id)init
{
    self.target = nil;
    return self;
}

-(void)forwardInvocation:(NSInvocation *)anInvocation
{
    if([self.target respondsToSelector:[anInvocation selector]]){
        [anInvocation invokeWithTarget:self.target];
    }
}

- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector
{
    return [self.target methodSignatureForSelector:selector];
}

@end

int main(int argc, const char **argv)
{
    @autoreleasepool {
        TBClassMock *mock = [[TBClassMock alloc] init];
        TBTestClass *foo = [[TBTestClass alloc] init];

        mock.target = foo;
        [mock outsideCalled];

        [mock release];
        [foo release];
    }
    return 0;
}

Выход:

2014-10-23 05:35:06.043 a.out[25483:507] TBTestClass:outsideCalled
2014-10-23 05:35:06.047 a.out[25483:507] TBTestClass:insideCalled
Другие вопросы по тегам