美文网首页
iOS 问题记录

iOS 问题记录

作者: Ian_ | 来源:发表于2018-12-07 16:28 被阅读8次

1. weak 不是万能的

class A: NSObject {
    var b: B?
    deinit {
        print("A died")
    }
}

class B: NSObject {
    var aa: A?
    func setA(a: A?) {
        if let a = a {
            aa = a
        }
    }
}

var b: B! = B()
var a: A? = A()

weak var aa = a
b.setA(a: aa)
a?.b = b
a = nil  // A 的 deinit 没走
b.aa = nil  // A 的 deinit 走了

上面的例子说明:__strong 不是瞎用的,避免循环引用,从根源做起。 let a = a相当于__strong。可以短暂在一个scope{}中强引用,不要持续持有,否则同样造成,循环引用。

2. 全局变量和单例的使用

这两个使用起来,很大的方便了代码,但一定要注意不要持有不该持有的对象,避免造成不释放。

3. weak 在闭包中的顺序很重要

class ClassA: NSObject {
    var closure: (() -> ())?
}

class ClassB: NSObject {
    var closure: (() -> ())?
}

class A: NSObject {
    var a = ClassA()
    
    override init() {
        super.init()
        a.closure = {
            [weak self] in
            let b = ClassB()
            b.closure = {
                print(self?.description ?? "??????")
            }
        }
    }
    
    deinit {
        print("A has died!")
    }
}

var a: A? = A()
a = nil // A 的 deinit 没走
class ClassA: NSObject {
    var closure: (() -> ())?
}

class ClassB: NSObject {
    var closure: (() -> ())?
}

class A: NSObject {
    var a = ClassA()
    
    override init() {
        super.init()
        a.closure = {
            let b = ClassB()
            b.closure = {
                [weak self] in
                print(self?.description ?? "??????")
            }
        }
    }
    
    deinit {
        print("A has died!")
    }
}

var a: A? = A()
a = nil // A 的 deinit 走了

上面两段代码就一句[weak self] in位置不一样, 但第一段的造成了循环引用,虽然在 b.closure 中使用 weak 来修饰,但由于 b.closure 也在 a.closure 中,所以a.closure 优先持有 self, 造成循环引用。第二段 b.closure 引用的是 a.closure中的weak self, 所以不会造成循环引用。

4. 关于 SnapKit ConstraintMakerEditable constraint 的循环引用

var centerConstraint: ConstraintMakerEditable?
centerConstraint = make.centerX.equalTo(target)

var centerConstraint: Constraint?
centerConstraint = make.centerX.equalTo(target).constraint

ConstraintMakerFinalizableConstraintMakerEditable的父类。
通过查看 SnapKit 源码,发现make.centerX.equalTo(target)返回的是ConstraintMakerFinalizable, 然而 internal let description: ConstraintDescriptionConstraintMakerFinalizable的一个属性,ConstraintDescription 又持有 Self, 当Self强持有ConstraintMakerFinalizable时,造成循环引用,而ConstraintMakerFinalizableconstraint返回的是internal let description: ConstraintDescriptionconstraint属性,Selfinternal let description: ConstraintDescription同时持有internal let description: ConstraintDescriptionconstraint属性,不会造成循环引用。

相关文章

网友评论

      本文标题:iOS 问题记录

      本文链接:https://www.haomeiwen.com/subject/rjothqtx.html