Last year, I wrote a swizzling API for my own use in patching Xcode; I wanted an easy way to define new method patches, and the API wound up being pretty nice:
[UIWindow pl_patchInstanceSelector: @selector(sendEvent:) withReplacementBlock: ^(PLPatchIMP *patch, UIEvent *event) { NSObject *obj = PLPatchGetSelf(patch); // Ignore 'remote control' events if (event.type == UIEventTypeRemoteControl) return; // Forward everything else return PLPatchIMPFoward(patch, void (*)(id, SEL, UIEvent *), event); }];
In light of Mattt Thompson's post on Method Swizzling today, I figured I'd brush it off, port it to armv7/armv7s/arm64, and share it publicly.
PLPatchMaster uses the same block trampoline allocator I originally wrote for PLBlockIMP, along with a set of custom trampolines.
It's similar to imp_implementationWithBlock() in implementation and efficiency; rather than simply re-ordering 'self' and '_cmd', we pass in enough state to allow forwarding the message to the original receiver's implementation.
Use it at your own risk; swizzling in production software is rarely, if ever, a particularly good idea.
The library can also be used to register patches to be applied to classes that have not yet been loaded:
[[PLPatchMaster master] patchFutureClassWithName: @"ExFATCameraDeviceManager" withReplacementBlock: ^(PLPatchIMP *patch, id *arg) { /* Forward the message to the next IMP */ PLPatchIMPFoward(patch, void (*)(id, SEL, id *)); /* Log the event */ NSLog(@"FAT camera device ejected"); }];
PLPatchMaster registers a listener for dyld image events, and will automatically swizzle the target class when its Mach-O image is loaded.
The soure code is available via the official repository, or via the GitHub mirror.