zoukankan      html  css  js  c++  java
  • 用block做事件回调来简化代码,提高开发效率

       我们在自定义view的时候,通常要考虑view的封装复用,所以如何把view的事件回调给Controller就是个需要好好考虑的问题,
    一般来说,可选的方式主要有target-action和delegate,以及这次要强烈推荐的block。
         target-action和delegate方式有个很不方便的地方,就是配置代码和action代码不在同一个地方,你肯定要多写一个selector方法或者delegate方法,这就带来一个问题,一旦代码比较长或者selector方法比较多,找起来就很不方便。把响应事件直接写在配置的地方才是理想的选择!而且实现这一理想选择的方式,就是用block来做事件回调~
         比如view上有个button,你需要把button的响应事件回调给controller,你应该怎么做呢?
    最麻烦的方式应该是用delegate,你要给view定义delegate协议,在controller中实现这个方法,而写了这么多代码,仅仅是为了响应button的事件(delegate方法还没办法跟设置view写到一起),太不划算了;
     
    能不能省了定义协议实现协议的步骤呢?
    能!用block就好了,给view添加一个block属性来做回调,在配置view的时候把事件用block传进去,然后设置button的相应事件就是去执行这个block,这样配置代码跟回调还能写一起,貌似很不错哦~~
    但是,给button添加一个事件,仅仅就是为了去执行一个block,这也是重复劳动啊;
    能不能把这步也优化了呢?
    能!直接用button的addTarget方法就行了嘛,addTarget方法不就是为了简化这种情况的嘛~但是这样又不能把配置代码跟相应事件写到一起了。。。
    能不能把这两种方式结合一下呢?
    能!用LXMBlockKit(https://github.com/Phelthas/LXMBlockKit)就可以了~
    LXMBlockKit 给UIButton封装了一个 - (void)addButtonCallback:(UIButton *sender) 方法,让button自己来做target,然后去响应事件,一举两得!!!
    不用敲重复的代码,只用去设置回调就好了!!!

    原来button事件的典型写法:

    [testButton addTarget:self action:@selector(handleButtonTapped:) forControlEvents:UIControlEventTouchUpInside]; 
    
    - (void)handleButtonTapped:(UIButton *)sender {    
        NSLog(@"handleButtonTapped");        
    }
    
    
    

    使用Block的写法:

       [testButton addButtonCallback:^(UIButton *sender) {
            NSLog(@"handleButtonTapped");
       }];
    
    
    
    可以看出来还是省了很多代码的,而且事件的回调就写在button的配置处,不用来回找~~
     
    不过也有必须要注意的地方:
    block回调中,务必使用weakSelf!直接使用self必定会导致循环引用!!!
    block回调中,务必使用weakSelf!直接使用self必定会导致循环引用!!!
    block回调中,务必使用weakSelf!直接使用self必定会导致循环引用!!!
    重要的事情说三遍!!!
    view只要add到Controller上,就会被强引用,而block是被view强引用的,所以如果block中又引用了self,那就一定会循环引用。。。
    这个我找了N久也没找到怎么用代码去判断有没有在block中引用self,所以没办法提示,只能靠自觉。。。没办法,养成好习惯吧
     
    类似的实现方式还有UIBarButtonItem和UIGesture,都可以用这种方式大大简化代码~
     
    NSNotificationCenter也可以用类似的方式,并且可以实现自动removeObserver,具体的实现方式稍有不同,主要是利用了属性在对象释放的时候会dealloc的原理,
    具体参考大神 nicklockwood的FXNotifications(https://github.com/nicklockwood/FXNotifications),我基本是按自己的代码习惯重新敲了一遍。
    也可以参考facebook的KVOController(https://github.com/facebook/KVOController
    或者大神zwaldowski的BlocksKit(https://github.com/zwaldowski/BlocksKit
     
    2017年6月10更新
    添加了NSTimer的block API,使用方法与其他分类类似,也要使用weakSelf;
    而且,因为NSTimer被添加到runloop的时候,runloop会强引用timer的target,所以计算NSTimer释放掉了,target可能还没释放,
    所以必须手动调用 invalidate()方法;
    一般在viewController中,invalidate方法写在viewController的dealloc中是不行的,因为runloop强引用viewController的话会导致viewController的dealloc不会被调用;
    使用这个block的API的话,可以将invalidate方法写在dealloc中,因为target是自定义的一个类,不影响viewController的生命周期。
     
     
    这个库的主要目的是简化自己平时常用的代码,所以并没有对各种事件各种控件封装的很完整,所以目前只有这几个分类,其他的等以后用到再慢慢加~
    有什么问题,欢迎讨论~ 
  • 相关阅读:
    Java for LeetCode 229 Majority Element II
    Java for LeetCode 228 Summary Ranges
    Java for LeetCode 227 Basic Calculator II
    Java for LintCode 颜色分类
    Java for LintCode 链表插入排序
    Java for LintCode 颠倒整数
    Java for LintCode 验证二叉查找树
    Java for LeetCode 226 Invert Binary Tree
    Java for LeetCode 225 Implement Stack using Queues
    Java for LeetCode 224 Basic Calculator
  • 原文地址:https://www.cnblogs.com/Phelthas/p/5759114.html
Copyright © 2011-2022 走看看