Can I intercept a method call in Objective-C? How?
Edit: Mark Powell\'s answer gave me a partial solution, the -forwardInvocation
Perhaps you want NSObject
's -forwardInvocation
method. This allows you to capture a message, retarget it and then resend it.
To do something when a method is called, you could try an events based approach. So when the method is called, it broadcasts an event, which is picked up by any listeners. I'm not great with objective C, but I just figured out something similar using NSNotificationCenter in Cocoa.
But if by "intercept" you mean "stop", then maybe you need more logic to decide wether the method should be called at all.
You do it by swizzling the method call. Assuming you want to grab all releases to 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@:");
You can get more details in the Objective C runtime documentation.
If you only want to log messages called from the outside (usually called from delegates; to see which kind of messages, when, etc.), you can override respondsToSelector like this:
- (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;
}