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: を置換している。