
Hook Objective-C Blocks avec Libffi. C'est un puissant outil AOP pour les blocs. Blockhook peut exécuter votre code avant / à la place / après invoquer un bloc. Blockhook peut même vous informer lorsqu'un test de bloc. Vous pouvez tracer tout le cycle de vie d'un bloc à l'aide de Blockhook!
Vous voulez accrocher les blocs passant aux méthodes? Essayez Blocktracker!
Blockhook a besoin de Libffi, qui prend en charge iOS, TVOS et MacOS. Vous pouvez exécuter BlockHookSample iOS , BlockHookSample tvOS ou BlockHookSample macOS Target.
Vous pouvez accrocher un bloc à l'aide de 4 modes (avant / à la place / après / mort). Cette méthode renvoie une instance BHToken pour plus de contrôle. Vous pouvez remove un BHToken ou définir une valeur de retour personnalisée dans sa propriété retValue . Appeler la méthode invokeOriginalBlock invoquera la mise en œuvre originale du bloc.
- (BHToken *)block_hookWithMode:(BlockHookMode)mode
usingBlock:( id )blockBlockhook est facile à utiliser. Ses API prennent l'exemple par des aspects. Voici un ensemble complet d'utilisation de Blockhook.
Ceci est un exemple de blocage d'accrochage dans tous les modes. Vous pouvez modifier la valeur de retour de bloc de 8 à 15. Ensuite, supprimez un crochet et vérifiez s'il réussit. Enfin, nous recevons un rappel lorsque 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);Voici le journal:
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
Parfois, vous souhaitez d'abord la connexion de l'utilisateur avant de rouler vers d'autres composants. Pour intercepter un bloc sans pirater le code des routeurs, vous pouvez utiliser 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);Cocoapods est un gestionnaire de dépendances pour les projets de cacao. Vous pouvez l'installer avec la commande suivante:
$ gem install cocoapods Pour intégrer BlockHook dans votre projet Xcode à l'aide de cocoapods, spécifiez-le dans votre Podfile :
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!
target 'MyApp' do
pod 'BlockHook'
end
Vous devez remplacer "MyApp" par le nom de votre projet.
Ensuite, exécutez la commande suivante:
$ pod installCarthage est un gestionnaire de dépendances décentralisé qui construit vos dépendances et vous fournit des cadres binaires.
Vous pouvez installer Carthage avec Homebrew en utilisant la commande suivante:
$ brew update
$ brew install carthage Pour intégrer BlockHook dans votre projet Xcode à l'aide de Carthage, spécifiez-le dans votre Cartfile :
github "yulingtianxia/BlockHook"
Exécutez carthage update pour construire le framework et faites glisser le BlockHook.framework construit dans votre projet Xcode.
Après l'importation de libffi, ajoutez simplement les deux fichiers BlockHook.h/m à votre projet.
yulingtianxia, [email protected]
Blockhook est disponible sous la licence MIT. Voir le fichier de licence pour plus d'informations.
Merci à MoblockClosure et aux aspects!