Objective-C中的拦截方法调用

luv*_*ere 18 methods objective-c intercept

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

编辑: 马克鲍威尔的回答给了我一个部分解决方案,-forwardInvocation方法.但是文档指出-forwardInvocation仅在向对象发送消息时才调用,该消息没有相应的方法.我想在所有情况下调用一个方法,即使接收器确实有那个选择器.

Lou*_*arg 23

你通过调用方法调用来实现.假设您要获取所有版本到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@:");
Run Code Online (Sandbox Code Playgroud)

您可以在Objective C运行时文档中获得更多详细信息.


Joh*_*lph 15

Objective-C中的拦截方法调用(假设它是一个Objective-C,而不是C调用)是通过一种称为方法调配的技术完成的.

您可以在此处找到有关如何实现该功能的介绍.有关如何在实际项目中实现方法调配的示例,请查看OCMock(Objective-C的隔离框架).


Ole*_*ann 11

发送在Objective-C消息被翻译成的功能的调用objc_msgSend(receiver, selector, arguments)或者其变体之一objc_msgSendSuper,objc_msgSend_stret,objc_msgSendSuper_stret.

如果可以更改这些功能的实现,我们可以拦截任何消息.不幸的是,它objc_msgSend是Objective-C运行时的一部分,无法覆盖.

通过谷歌搜索,我在Google Books上找到了一篇论文:Charlotte Pii Lunau的过程控制应用反射架构.本文通过将对象的isa类指针重定向到自定义MetaObject类的实例来引入hack .因此,用于修改对象的消息将发送到MetaObject实例.由于MetaObject类没有自己的方法,因此可以通过将消息转发给修改后的对象来响应前向调用.

本文不包括源代码的有趣内容,我不知道这种方法是否会在Cocoa中产生副作用.但尝试可能会很有趣.


emp*_*emp 5

如果要从应用程序代码中记录消息发送,则-forwardingTargetForSelector:tip是解决方案的一部分.
包裹你的对象:

@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
Run Code Online (Sandbox Code Playgroud)

现在做这样的事情:

Interceptor *i = [[[Interceptor alloc] init] autorelease];
NSFetchedResultsController *controller = [self setupFetchedResultsController];
i.interceptedTarget = controller;
controller = (NSFetchedResultsController *)i;
Run Code Online (Sandbox Code Playgroud)

你将有一个消息发送日志.注意,截取对象内发送的发送不会被拦截,因为它们将使用原始对象'self'指针发送.