前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS循环引用

iOS循环引用

作者头像
用户1941540
发布2018-05-11 13:29:48
7770
发布2018-05-11 13:29:48
举报
文章被收录于专栏:ShaoYL

iOS循环引用

  • 当前类的闭包/Block属性,用到了当前类,就会造成循环引用
    1. 此闭包/Block应该是当前类的属性,我们经常对Block进行copy,copy到堆中,以便后用。
    2. 单方向引用是不会产生循环引用。需要self引用闭包/Block,Block中使用self。
  • 有两个规则:
    1. 如果你是通过引用来访问一个实例变量,那么将强引用至self。
    2. 如果你是通过值来访问一个实例变量,那么将直接强引用至这个“值”变量。

Object-C Block循环引用情况

  • 一般来说我们总会在设置Block之后,在合适的时间回调Block,而不希望回调Block的时候Block已经被释放了,所以我们需要对Block进行copy,copy到堆中,以便后用。
  • 当一个Block被Copy的时候,如果你在Block里进行了一些调用,那么将会有一个强引用指向这些调用方法的调用者。

swift 中闭包循环引用情况

代码语言:javascript
复制
class ViewController: UIViewController {
    // 1.闭包是当前类属性
    var allCallBack :(()->())?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        CyclicLead {
            // 闭包引用当前类
            print(self.view)
        }
    }

    // 循环引用的方法
    func CyclicLead(completionBack:@escaping ()->()) -> Void {
        // 2.当前类引用闭包
        allCallBack = completionBack
        
        DispatchQueue.global().async {
            
            DispatchQueue.main.async {
                completionBack()
            }
        }
    }
    
    // 当对象销毁时会调用
    deinit {
        print("销毁了")
    }
}

解除循环引用

OC方式

  • 方式一
代码语言:javascript
复制
__weak typeof(self) weakSelf = self;
self.block = ^(NSString *name){
    NSLog(@"view:%@", weakSelf.view);
};
  • 方式二
代码语言:javascript
复制
__unsafe_unretained typeof (self) weakSelf = self;
[self loadData:^{
    NSLog(@"%@", weakSelf.view);
}];

swift方式

  • 方案一:
    • 使用weak,对当前控制器使用弱引用
代码语言:javascript
复制
    // 解决方案一:
    /*
    细节1:var ,weak 只能修饰var,不能修饰 let
     'weak' must be a mutable variable,
      because it may change at runtime
      weak 可能会被在运行时被修改 -> 指向的对象一旦被释放,会被自动设置为nil
    细节2: weakSelf?  weakSelf!   两种解包方式
    ?可选解包 - 如果self已经被释放,不会向对象发送getter消息
        可选解包只是单纯的发送消息,没有计算
    ! 强行解包 - 如果self已经被释放,强行解包会导致崩溃
        强行解包可以参与计算,可选项不能直接参与到计算
    */
    weak var weakSelf = self
    CyclicLead {
        print(weakSelf?.view)
    }
  • 方案二:
    • 和方案一类型,只是书写方式更加简单
    • 可以写在闭包中,并且在闭包中用到的self都是弱引用
代码语言:javascript
复制
CyclicLead {[weak self]()->() in            
    print(self?.view)
}
// 缩减写法
CyclicLead {[weak self] in
    print(self?.view)
}
  • 方案三:
    • 使用关键字unowned
    • 从行为上来说 unowned 更像OC中的 unsafe_unretained
    • unowned 表示:即使它原来引用的对象被释放了,仍然会保持对被已经释放了的对象的一个 "无效的" 引用,它不能是 Optional 值,也不会被指向 nil
    • [unowned self]表示 {} 中的所有 self 都是 assign 的,不会强引用,但是,如果对象释放,指针地址不会变化如果对象被释放,继续调用,就会出现野指针的问题
代码语言:javascript
复制
CyclicLead {[unowned self]()->() in
    print(self?.view)
}

// 缩减写法
CyclicLead {[unowned self] in
    print(self?.view)
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-09-02 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • iOS循环引用
    • Object-C Block循环引用情况
      • swift 中闭包循环引用情况
        • 解除循环引用
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档