【问题标题】:iOS: NSProxy can't hook method called inside of Class itselfiOS:NSProxy 不能挂钩在类本身内部调用的方法
【发布时间】:2014-07-18 17:46:37
【问题描述】:

我使用 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 来调整类的所有方法,因为我认为这太挑剔而且不是一个好方法。

【问题讨论】:

  • TBTestClass.h中声明了哪些方法?

标签: ios methods hook nsproxy


【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-02
    • 1970-01-01
    • 2012-11-15
    • 2021-10-23
    • 1970-01-01
    • 2021-09-13
    • 2020-02-14
    相关资源
    最近更新 更多