• Stars
    star
    836
  • Rank 54,534 (Top 2 %)
  • Language
    C
  • License
    MIT License
  • Created over 6 years ago
  • Updated 10 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Hook Objective-C blocks. A powerful AOP tool.

BlockHook

Platform CI Status Version Carthage compatible codecov Codacy Badge GitHub release Twitter Follow

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!

🌟 Features

  • Easy to use. Keep your code clear.
  • Support 4 hook modes: Before, Instead, After and Dead.
  • Let you modify return value and arguments.
  • Support invoking original implementation.
  • Remove hook at any time.
  • Traverse all hook tokens of block.
  • Provide block mangle name.
  • Self-managed tokens.
  • Support custom struct.
  • 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.

- (BHToken *)block_hookWithMode:(BlockHookMode)mode
                     usingBlock:(id)block

BlockHook is easy to use. Its APIs take example by Aspects. Here 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.

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:<BHInvocation: 0x60b00003c370>
3 + 5 = 8, z is a NSObject: <NSObject: 0x6020000279d0>
let me see original result: 0
hook instead: '+' -> '*'
hook after block! 3 * 5 = 15
hooked result:15
block dead! token:<BHToken: 0x60d000004bd0>
remove tokens, original block
3 + 5 = 8, z is a NSObject: <NSObject: 0x6020000279d0>
original result:8

Block Interceptor

Sometimes you want user login first before routing to other components. To intercept a block without hacking into code of routers, you can use block interceptor.

NSObject *testArg = [NSObject new];
NSObject *testArg1 = [NSObject new];
    
NSObject *(^testblock)(NSObject *) = ^(NSObject *a) {
    return [NSObject new];
};
    
[testblock block_interceptor:^(BHInvocation *invocation, IntercepterCompletion  _Nonnull completion) {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        NSObject * __unsafe_unretained arg;
        [invocation getArgument:&arg atIndex:1];
        NSLog(@"Original argument:%@", arg);
        [invocation setArgument:(void *)&testArg1 atIndex:1];
        completion();
    });
}];
    
testblock(testArg);

📲 Installation

CocoaPods

CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:

$ gem install cocoapods

To integrate BlockHook into your Xcode project using CocoaPods, specify it in your Podfile:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!
target 'MyApp' do
	pod 'BlockHook'
end

You need replace "MyApp" with your project's name.

Then, run the following command:

$ pod install

Carthage

Carthage is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.

You can install Carthage with Homebrew using the following command:

$ brew update
$ brew install carthage

To integrate BlockHook into your Xcode project using Carthage, specify it in your Cartfile:

github "yulingtianxia/BlockHook"

Run carthage update to build the framework and drag the built BlockHook.framework into your Xcode project.

Manual

After importing libffi, just add the two files BlockHook.h/m to your project.

❤️ Contributed

  • If you need help or you'd like to ask a general question, open an issue.
  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.

📚 Article

👨🏻‍💻 Author

yulingtianxia, [email protected]

👮🏻 License

BlockHook is available under the MIT license. See the LICENSE file for more info.

Thanks to MABlockClosure and Aspects!

More Repositories

1

FishChat

Hook WeChat.app on non-jailbroken devices.
1,118
star
2

TBActionSheet

A Custom&Powerful Action Sheet For iOS. 一个 ActionSheet 满足所有样式!超高自由度的可定制!
Objective-C
950
star
3

MessageThrottle

A lightweight Objective-C message throttle and debounce library.
Objective-C
823
star
4

AppOrderFiles

The easiest way to generate order files for Mach-O using Clang. Improving App Performance.
Objective-C
652
star
5

pbxprojHelper

A macOS tool help you handling project.pbxproj files. Written in Swift 5!
Swift
484
star
6

TBUIAutoTest

Generating UI test label automatically for iOS.
Objective-C
349
star
7

FuckFakeGitHubStars

GitHub 虚假 Star 净网行动
Python
265
star
8

Core-ML-Sample

A Demo using Vision Framework building on Core ML Framework
Swift
218
star
9

YXYDashLayer

Colorful Rounded Rect Dash Border
Objective-C
175
star
10

SimilarImageHunter

Mac 上寻找相似内容的图片工具
Objective-C
172
star
11

HardChoice

有时候作抉择真的很痛苦,Swift写的生活类APP
Swift
92
star
12

Spiral

A Game Developed with Swift and SpriteKit
Swift
88
star
13

AudioEmotion

Recognize Audio Emotion.
Python
86
star
14

BlockTracker

Tracking block args of Objective-C method based on BlockHook
Objective-C
78
star
15

PhotoAssessment

Photo Assessment using Core ML and Metal.
Objective-C
72
star
16

ColorAtom

用SpriteKit写的关于正能量的小游戏
Objective-C
49
star
17

Algorithm-Experiment

Algorithm experiment code written by Swift
Swift
46
star
18

Self-Sizing-CollectionView-Demo

This is the Demo showed in http://yulingtianxia.com/blog/2014/08/17/New-in-Table-and-Collection-Views/
Swift
35
star
19

YXYNumberAnimationLabel

一个数字动画Label
Objective-C
33
star
20

TFSHelper

Mac 上自动捕获并打开 TFS 链接的小工具
Swift
32
star
21

WebViewImageClick

看美图必备
Objective-C
27
star
22

ClassWrittenInSwift

Something for Class written in Swift.
Objective-C++
18
star
23

ImageMask

iOS刮刮卡的实现
Objective-C
17
star
24

javaQQ

用java写的QQ客户端,简单地聊天和发送文件功能
Java
14
star
25

DirtyWords-for-Xcode

Highlight dirty words in Xcode.
Swift
11
star
26

HandGestureCNN

Trainning Inception v3 model with Keras, and predict with MPS on iOS.
Swift
10
star
27

ChangYou

畅游室内导航
Java
7
star
28

Blog-Hexo-Source

My Blog Source
JavaScript
5
star
29

yulingtianxia.github.io

我的技术博客
HTML
5
star
30

MyCDDemo

Core Data Demo
Objective-C
4
star
31

Linger

临哥让我做的内部使用的 Mac 平台简易日志分析工具,不知道起啥名字好,就叫 Linger 吧
Objective-C
3
star
32

Pebble-MoHa

Pebble Watchface +1s
C
2
star
33

FavoriteGirls

Machine Learning Demo
Python
2
star
34

MyFirstGame

无聊写的小游戏
Objective-C
1
star
35

LeetCode

记录LeetCode刷题
C++
1
star