Block 使用心得

  1. Block 与 Method 最大的区别在于,Block 能够捕获上下文中的变量;
  2. Block 能够捕获上下文中的变量是有代价的,而这个代价就是:
    • Block 本质上是对象,alloc release 会有额外开销;
    • Block 在使用中,堆 Block 容易引起循环引用问题;栈 Block 容易引起 SIGSEGV;

因为堆 Block 容易引起循环引用问题,所以 UIKit 中使用的是 Action 模式、Delegate 模式等。
因为栈 Block 在非主线程中,容易遇到 SIGSEGV 问题,所以常规方法 封装方法

结论

  1. 在 ViewController - View 层面的接口设计中,应该避免使用 Block,而使用 Action 模式、Delegate 模式等常规 Callback 手段;
  2. 在 ViewModel - ViewController 层面的接口设计中,分为两种情况:
    • ViewModel 是单例,接口需要捕获上下文中的变量。这种情况应该使用 Block, 简化开发,提高可维护性;
    • ViewModel 不是单例,那么与 ViewController - View 的情况是类似的。无论是 ViewController 持有 ViewModel,还是 ViewModel 持有 ViewController,都容易引起循环引用问题,极大的增加开发难度。这种情况不应该使用 Block。

结论

今天又有了新的收获

  1. 如非必要,尽可能少的使用 Block
  2. 在 Block 中访问 self 的实例变量,必须显式声明,避免编译器语法糖导致的循环应用。

Block 中访问实例变量,不显式声明 weakSelf->,会引起循环引用

preferred:
^(NSString *title, NSString *url) {
    NSLog(@"%@", weakSelf->testString)
};
not preferred:
^(NSString *title, NSString *url) {
    NSLog(@"%@", testString)
};

使用 EXTScope,如果不显示声明 self->,也会引起循环引用

preferred:
@weakify(self)
^(NSString *title, NSString *url) {
    @strongify(self);
    NSLog(@"%@", self->testString)
};
not preferred:
@weakify(self)
^(NSString *title, NSString *url) {
    @strongify(self);
    NSLog(@"%@", testString)
};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容