BlockからIMPを作り出す関数 imp_implementationWithBlock() を使ったテクニック。面白い。
(以下、引用)
こんなのを用意しておけば
void
replaceMethodWithBlock(Class cls, SEL sel, id (^blockGen)(SEL, IMP))
{
IMP originalImplementation = NULL;
Method originalMethod = class_getInstanceMethod(cls, sel);
if (!originalMethod) {
[NSException raise:NSInvalidArgumentException format:@"method not found:%s", sel];
}
originalImplementation = method_getImplementation(originalMethod);
id block = blockGen(sel, originalImplementation);
if (!block) {
return;
}
IMP imp = imp_implementationWithBlock((__bridge void*) block);
method_setImplementation(originalMethod, imp);
}こんな感じで簡単に書ける。
replaceMethodWithBlock([NSWindow class], @selector(mouseDown:),
// block to generate block for method.
(id) ^(SEL selector, IMP originalImplimentation) {
// block for method.
void (^block)(id, NSEvent*) = ^(id self, NSEvent *theEvent) {
NSLog(@"[BEFORE] mouseDown:%@", theEvent);
originalImplimentation(self, selector, theEvent);
NSLog(@"[AFTER] mouseDown:");
};
return block;
});上記は NSWindow の mouseDown: 前後にログを書きだすブロックで mouseDown: を置換している。


