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