You can hijack the desired methods on UIResponder
to add logging and then call the original method. Here's an example:
#import <Foundation/NSObjCRuntime.h>
@interface UIResponder (MYHijack)
+ (void)hijack;
@end
@implementation UIResponder (MYHijack)
+ (void)hijackSelector:(SEL)originalSelector withSelector:(SEL)newSelector
{
Class class = [UIResponder class];
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method categoryMethod = class_getInstanceMethod(class, newSelector);
method_exchangeImplementations(originalMethod, categoryMethod);
}
+ (void)hijack
{
[self hijackSelector:@selector(touchesBegan:withEvent:) withSelector:@selector(MYHijack_touchesBegan:withEvent:)];
}
- (void)MYHijack_touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"touches!");
[self MYHijack_touchesBegan:touches withEvent:event]; // Calls the original version of this method
}
@end
Then somewhere in your app (I sometimes put it in main()
itself), just call [UIResponder hijack]
. As long as the UIResponder
subclass calls super
at some point, your code will be injected.
method_exchangeImplementations()
is a beautiful thing. Be careful with it of course; it's great for debugging, but very confusing if used indiscriminately.