在Objective-C截取方法调用(Intercept method call in Object

2019-09-01 00:31发布

我可以拦截在Objective-C的方法调用? 怎么样?

编辑:“ 马克·鲍威尔的回答给了我一个局部的解决方案,-forwardInvocation方法。 但文档指出,当一个物体被发送对于其没有对应的方法的消息-forwardInvocation才调用。 我想在任何情况下被调用的方法,即使接收器确实有一个选择。

Answer 1:

您可以通过交叉混合的方法调用做到这一点。 假设你想抓住所有版本中NSTableView的:

static IMP gOriginalRelease = nil;
static void newNSTableViewRelease(id self, SEL releaseSelector, ...) {
   NSLog(@"Release called on an NSTableView");
   gOriginalRelease(self, releaseSelector);
}


  //Then somewhere do this:
  gOriginalRelease = class_replaceMethod([NSTableView class], @selector(release), newNSTableViewRelease, "v@:");

你可以得到目标C运行时更详细的文档 。



Answer 2:

拦截方法在Objective-C调用(asuming这是一个Objective-C,不是C调用)与调用的方法交叉混合技术来完成

你可以找到关于如何实现的介绍在这里 。 举一个例子方法混写如何在实际项目实施检查OCMock (对于Objective-C中的隔离框架)。



Answer 3:

发送在Objective-C消息被转换成函数的调用objc_msgSend(receiver, selector, arguments)或它的变体之一objc_msgSendSuperobjc_msgSend_stretobjc_msgSendSuper_stret

如果它是可以改变的,这些功能的实现,我们可以拦截任何消息。 不幸的是, objc_msgSend是Objective-C运行的一部分,不能被重写。

谷歌搜索,我发现在谷歌图书的论文: 由夏洛特PII Lunau过程控制应用的反射架构 。 本文通过重定向对象的介绍黑客攻击isa类指针到自定义元对象类的一个实例。 因而旨在被修改的对象的消息发送到元对象实例。 由于元对象类有没有自己的方法,它可以通过随后将消息转发到已修改的对象应对前进调用。

本文不包括源代码的有趣的位,我不知道,如果这种做法将在可可的副作用。 但是,它可能是有趣的尝试。



Answer 4:

如果你想记录的消息从应用程序代码发送的-forwardingTargetForSelector:尖是解决方案的一部分。
包装你的对象:

@interface Interceptor : NSObject
@property (nonatomic, retain) id interceptedTarget;
@end

@implementation Interceptor
@synthesize interceptedTarget=_interceptedTarget;

- (void)dealloc {
    [_interceptedTarget release];
    [super dealloc];
}

- (id)forwardingTargetForSelector:(SEL)aSelector {
    NSLog(@"Intercepting %@", NSStringFromSelector(aSelector));
    return self.interceptedTarget;
} 

@end

现在做这样的事情:

Interceptor *i = [[[Interceptor alloc] init] autorelease];
NSFetchedResultsController *controller = [self setupFetchedResultsController];
i.interceptedTarget = controller;
controller = (NSFetchedResultsController *)i;

和消息发送,你将有一个日志。 注意,并将从监听对象内发送不会被拦截,因为他们将使用原始对象的“自我”指针被发送。



Answer 5:

如果你只是想记录从外部调用的消息(通常代表呼吁,看看哪一种的消息的时候,等),可以覆盖respondsToSelector是这样的:

- (BOOL)respondsToSelector:(SEL)aSelector {
NSLog(@"respondsToSelector called for '%@'", NSStringFromSelector(aSelector));

// look up, if a method is implemented
if([[self class] instancesRespondToSelector:aSelector]) return YES;

return NO;

}



Answer 6:

创建的子类, NSProxy和实施-forwardInvocation:-methodSignatureForSelector:-forwardingTargetForSelector:如果你只是指挥它到第二个对象,而不是用自己的方法摆弄)。

NSProxy是专为执行一类-forwardInvocation:对。 它有几个方法,但主要是你不希望他们被抓获。 例如,醒目的引用计数方法将防止代理被释放,除了垃圾收集下。 但是,如果有具体的方法NSProxy ,你绝对需要转发,可以专门重写方法,并调用-forwardInvocation:手动。 这样做仅仅是因为一个方法在下面列出音符NSProxy文档并不意味着NSProxy实现它,仅仅是预计所有代理的对象都有它。

如果这不会为你工作,提供有关情况的其他详细信息。



Answer 7:

也许你想NSObject-forwardInvocation方法。 这可以让你捕捉到一条消息,重新定位它,然后重新发送。



Answer 8:

你可以用你自己的,它不不管你想在“拦截”做,并呼吁通过对原执行的一个调酒方法调用。 混写与class_replaceMethod()完成。



Answer 9:

一个方法调用,没有。 消息发送,是的,但你将不得不多很多描述性的,如果你想有一个很好的答案如何。



Answer 10:

做一些事情,当一个方法被调用时,你可以尝试的活动为基础的方法。 因此,当方法被调用时,它广播的事件,这是任何听众回升。 我不是伟大的目标C,但我只是想出了类似的东西使用NSNotificationCenter可可。

但是,如果通过“拦截”你的意思是“停止”,那么也许你需要更多的逻辑来决定将来的方法应该是在所有调用。



文章来源: Intercept method call in Objective-C