本篇文章主要介绍了"BlocksKit初见:一个支持将delegate转换成block的Cocoa库",主要涉及到github,Dictionary方面的内容,对于移动开发感兴趣的同学可以参考一下:
简介项目主页: https://github.com/zwaldowski/BlocksKitBlocksKit 是一个开源的框架,对 Cocoa 进行了扩展,...
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