# BlockHook **Repository Path**: leegithub/BlockHook ## Basic Information - **Project Name**: BlockHook - **Description**: Hook Objective-C blocks with libffi. It's a powerful AOP tool for blocks. BlockHook can run your code before/instead/after invoking a block. BlockHook can even notify you when a block dealloc. - **Primary Language**: Objective-C - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-07-27 - **Last Updated**: 2022-04-06 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README
[](http://cocoapods.org/pods/BlockHook) [](https://travis-ci.org/yulingtianxia/BlockHook) [](http://cocoapods.org/pods/BlockHook) [](https://github.com/Carthage/Carthage) [](https://codecov.io/gh/yulingtianxia/BlockHook) [](https://app.codacy.com/app/yulingtianxia/BlockHook?utm_source=github.com&utm_medium=referral&utm_content=yulingtianxia/BlockHook&utm_campaign=Badge_Grade_Dashboard) [](https://github.com/yulingtianxia/BlockHook/releases) [](https://twitter.com/yulingtianxia) # BlockHook Hook Objective-C blocks with libffi. It's a powerful AOP tool for blocks. BlockHook can run your code before/instead/after invoking a block. BlockHook can even notify you when a block dealloc. You can trace the whole lifecycle of a block using BlockHook! **Want to hook blocks passing to methods? Try [BlockTracker](https://github.com/yulingtianxia/BlockTracker)!** ## 🌟 Features - [x] Easy to use. Keep your code clear. - [x] Support 4 hook modes: Before, Instead, After and Dead. - [x] Let you modify return value and arguments. - [x] Support invoking original implementation. - [x] Remove hook at any time. - [x] Traverse all hook tokens of block. - [x] Provide block mangle name. - [x] Self-managed tokens. - [x] Support custom struct. - [x] Support Carthage & CocoaPods. ## 🔮 Example BlockHook needs libffi, which supports iOS, tvOS and macOS. You can run `BlockHookSample iOS`, `BlockHookSample tvOS` or `BlockHookSample macOS` target. ## 🐒 How to use ### Just Hook You can hook a block using 4 modes (before/instead/after/dead). This method returns a `BHToken` instance for more control. You can `remove` a `BHToken`, or set custom return value to its `retValue` property. Calling `invokeOriginalBlock` method will invoke original implementation of the block. ```objc - (BHToken *)block_hookWithMode:(BlockHookMode)mode usingBlock:(id)block ``` BlockHook is easy to use. Its APIs take example by Aspects. [Here](https://github.com/yulingtianxia/BlockHook/blob/master/BlockHookSampleTests/BlockHookSampleTests.m) is a full set of usage of BlockHook. This is an example for hooking block in all modes. You can change block return value from 8 to 15. Then remove some hook and check if it is successful. Finally we get callback when block dealloc. ```objc NSObject *z = NSObject.new; int(^block)(int x, int y) = ^int(int x, int y) { int result = x + y; NSLog(@"%d + %d = %d, z is a NSObject: %@", x, y, result, z); return result; }; BHToken *token = [block block_hookWithMode:BlockHookModeDead|BlockHookModeBefore|BlockHookModeInstead|BlockHookModeAfter usingBlock:^(BHInvocation *invocation, int x, int y) { int ret = 0; [invocation getReturnValue:&ret]; switch (invocation.mode) { case BlockHookModeBefore: // BHInvocation has to be the first arg. NSLog(@"hook before block! invocation:%@", invocation); break; case BlockHookModeInstead: [invocation invokeOriginalBlock]; NSLog(@"let me see original result: %d", ret); // change the block imp and result ret = x * y; [invocation setReturnValue:&ret]; NSLog(@"hook instead: '+' -> '*'"); break; case BlockHookModeAfter: // print args and result NSLog(@"hook after block! %d * %d = %d", x, y, ret); break; case BlockHookModeDead: // BHInvocation is the only arg. NSLog(@"block dead! token:%@", invocation.token); break; default: break; } }]; NSLog(@"hooked block"); int ret = block(3, 5); NSLog(@"hooked result:%d", ret); // remove token. [token remove]; NSLog(@"remove tokens, original block"); ret = block(3, 5); NSLog(@"original result:%d", ret); ``` Here is the log: ``` hooked block hook before block! invocation: