2

我使用 NSProxy 来模拟一个类,并希望挂钩该类的所有调用。但是只有类外调用的方法才被钩住,类内没有调用的方法。下面是我的代码:

在我的AppDelegate.m中,TBClassMockNSProxy的子类

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因为我认为这太挑剔而且不是一个好方法。

4

1 回答 1

-2

我猜你误解了 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
于 2014-10-23T00:12:11.987 回答