BlocksKit初见:一个支持将delegate转换成block的Cocoa库
来源:互联网 发布:淘宝商品设置多个选项 编辑:程序博客网 时间:2024/05/29 18:48
简介
- 项目主页: https://github.com/zwaldowski/BlocksKit
BlocksKit 是一个开源的框架,对 Cocoa 进行了扩展,将许多需要通过 delegate 调用的方法转换成了 block。在很多情况下,blocks 比 delegate 要方便简单,因为 block 是紧凑的,可以使代码简洁,提高代码可读性,另外 block 还可以进行异步处理。使用 block 要注意避免循环引用。
目录结构
BlocksKit 的所有方法都以bk_
开头,这样可以方便地列出所有 BlocksKit 的所有方法。BlocksKit 主要目录结构
- Core:存放 Foundation 相关的 Block category,如 NSObject、NSTimer、NSarray、NSDictionary、NSSet、NSIndexSet、NSMutableArray等
- DynamicDelegate:动态代理(消息转发机制)
- UIKit:扩展了 UIAlertView,UIActionView,UIButton 等
最常用的是 UIKit Category,它为 UIAlertView,UIActionSheet,UIButton,UITapGestureRecognizer 等提供了 blocks。
用法实例
UIAlertView 和 UIActionSheet 用法示例:
UIAlertView *alertView = [[UIAlertView alloc] bk_initWithTitle:@"提示" message:@"提示信息"];[alertView bk_setCancelButtonWithTitle:@"取消" handler:nil];[alertView bk_addButtonWithTitle:@"确定" handler:nil];[alertView bk_setDidDismissBlock:^(UIAlertView *alert, NSInteger index) { if (index == 1) { NSLog(@"%ld clicked",index); }}];[alertView show];
[[UIActionSheet bk_actionSheetCustomWithTitle:nil buttonTitles:@[@"查看", @"退出"] destructiveTitle:nil cancelTitle:@"取消" andDidDismissBlock:^(UIActionSheet *sheet, NSInteger index) {}] showInView:self.view];
UIButton 和 UITapGestureRecognizer 用法示例:
UIButton *button = [[UIButton alloc] init];[button bk_addEventHandler:^(id sender) {} forControlEvents:UIControlEventTouchUpInside];
UITapGestureRecognizer *tapGestureRecognizer = [UITapGestureRecognizer bk_recognizerWithHandler:^(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location) { if (state == UIGestureRecognizerStateRecognized) { ... }}];
UIButton 和 UIGesture 将 target-action 转换成 block,实现较简单:
- (id)bk_initWithHandler:(void (^)(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location))block delay:(NSTimeInterval)delay{ self = [self initWithTarget:self action:@selector(bk_handleAction:)]; if (!self) return nil; self.bk_handler = block; self.bk_handlerDelay = delay; return self;}- (void)bk_handleAction:(UIGestureRecognizer *)recognizer{ void (^handler)(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location) = recognizer.bk_handler; if (!handler) return; ... if (!delay) { block(); return; } ...}
delegate 转换成 block 实际上使用了消息转发机制,是 BlocksKit 源码中最难理解的部分。
原理分析: 消息转发机制
当一个对象收到它没实现的消息的时候,通常会发生如下的情况。
- 调用
+(BOOL)resolveInstanceMethod:(SEL)aSEL
,如果对象在这里动态添加了selector 的实现方法,则消息转发结束,否则执行步骤2 - 调用
- (id)forwardingTargetForSelector:(SEL)aSelector
,在这里你可以将消息转发给其他对象,如果实现则消息转发结束,否则执行步骤3 - 执行完整的消息转发机制,调用
-(void)forwardInvocation:(NSInvocation *)invocation
在这一步,你可以修改消息的任何内容,包括目标(target),selector,参数。如果没有实现在这里还未实现转发则程序将抛出异常。
原理实例分析
BlocksKit 动态代理实现方式是最后一步,即-(void)forwardInvocation:(NSInvocation *)invocation
,使得动态代理能够接受任意消息。
以UIAlertView为例,UIAlertView在运行时动态关联了A2DynamicUIAlertViewDelegate
@implementation UIAlertView (BlocksKit)@dynamic bk_willShowBlock, bk_didShowBlock, bk_willDismissBlock, bk_didDismissBlock, bk_shouldEnableFirstOtherButtonBlock;+ (void)load{ @autoreleasepool { [self bk_registerDynamicDelegate]; [self bk_linkDelegateMethods:@{ @"bk_willShowBlock": @"willPresentAlertView:", @"bk_didShowBlock": @"didPresentAlertView:", @"bk_willDismissBlock": @"alertView:willDismissWithButtonIndex:", @"bk_didDismissBlock": @"alertView:didDismissWithButtonIndex:", @"bk_shouldEnableFirstOtherButtonBlock": @"alertViewShouldEnableFirstOtherButton:" }]; }}
A2DynamicUIAlertViewDelegate 是 A2DynamicDelegate 的子类,并实现了UIAlertViewDelegate 的方法
代理消息的转发由 A2DynamicDelegate 完成
- (void)forwardInvocation:(NSInvocation *)outerInv{ SEL selector = outerInv.selector; A2BlockInvocation *innerInv = nil; if ((innerInv = [self.invocationsBySelectors bk_objectForSelector:selector])) { [innerInv invokeWithInvocation:outerInv]; } else if ([self.realDelegate respondsToSelector:selector]) { [outerInv invokeWithTarget:self.realDelegate]; }}
注: 文章由我们 iOS122(http://www.ios122.com)的小伙伴 @鱼
整理,喜欢就一起参与: iOS122 任务池
- BlocksKit初见:一个支持将delegate转换成block的Cocoa库
- delegate 和 block 的区别
- block 与 delegate 的区别
- block 与 delegate 的区别
- delegate和block的选择
- block和delegate的使用
- delegate block 通知的区别
- block与delegate的认识
- block 与delegate 的区别
- Cocoa处理消息的方法:Delegate
- Cocoa处理消息的方法:Delegate
- Objective-C Cocoa的delegate机制解释
- Cocoa处理消息的方法- Delegate
- [Cocoa]处理消息的方法-Delegate
- 一个很不错的框架,blockskit, 待实践
- 初见《一个操作系统的实现》
- 将Maven项目转换成Eclipse支持的Java项目
- 将Maven项目转换成Eclipse支持的Java项目
- PHP 开发的 API 多版本管理实践
- 网站攻击的三种手段及预防方法
- 学习篇--log4j.properties
- JavaScript之解释与执行
- codeforce 550c Divisibility by Eight (DFS)
- BlocksKit初见:一个支持将delegate转换成block的Cocoa库
- SpringMvc多视图整合配置教程(jsp、velocity、freemarker)
- 浅谈json转c#对象
- JavaScript基础(2):什么是“闭包”?
- win10+ubuntu14.04双系统有线网络问题
- 软件测试会大概问的一些问题整理续
- Linux 下 NFS服务的搭建
- javascript动态获取当前页面的url
- 分享:EditText默认不弹出软件键盘