美文网首页
swift防止循环引用简单整理

swift防止循环引用简单整理

作者: 悃破 | 来源:发表于2017-10-23 10:39 被阅读107次

    weak

    弱引用不会对其引用的实例保持强引用,因而不会阻止 ARC 销毁被引用的实例。这个特性阻止了引用变为循环强引用。ARC 会在引用的实例被销毁后自动将其赋值为nil。并且因为弱引用可以允许它们的值在运行时被赋值为nil,所以它们会被定义为可选类型变量,而不是常量。

    unowned

    和弱引用类似,无主引用不会牢牢保持住引用的实例。和弱引用不同的是,无主引用在其他实例有相同或者更长的生命周期时使用。无主引用通常都被期望拥有值。不过 ARC 无法在实例被销毁后将无主引用设为nil,因为非可选类型的变量不允许被赋值为nil。

    代理的循环引用

    使用weak标记
    如下定义两个协议

    protocol TestProtocol: class  {    
        func testProtocolFunc()
    }
    
    @objc protocol TestProtocol2 {
        func testProtocolFunc2()
    }
    

    ⚠️注意:在使用weak标记时delegate时,协议需要继承class或用@objc标记,否则会爆错。'weak' may only be applied to class and class-bound protocol types, not 'TestProtocol'
    使用协议时:

    class TestClass {
        weak var delegate: TestProtocol?
        weak var delegate2: TestProtocol2?
        func test() {
            self.delegate?.testProtocolFunc()
            self.delegate2?.testProtocolFunc2()
        }
    }
    

    闭包的防止循环引用

    闭包防止循环引用时使用weak unowned的原则:
    a、在闭包和捕获的实例总是互相引用并且总是同时销毁时,将闭包内的捕获定义为无主引用。
    b、相反的,在被捕获的引用可能会变为nil时,将闭包内的捕获定义为弱引用。弱引用总是可选类型,并且当引用的实例被销毁后,弱引用的值会自动置为nil。这使我们可以在闭包体内检查它们是否存在。
    c、如果被捕获的引用绝对不会变为nil,应该用无主引用,而不是弱引用。
    如(a、b暂未遇到合适的例子):

    class SwiftViewController: UIViewController {
    
        var swiftBlock: ((String) -> Void)?
        var name = ""
        
        override func viewDidLoad() {
            super.viewDidLoad()
    
            self.swiftBlock = { [unowned self] str in
                print("\(self.title ?? "没有标题")")
            }
        }
        
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    
            if let block = self.swiftBlock {
                block("测试swiftblock")
            }
        }
    
        deinit {
            print("SwiftViewController销毁了")
        }
    
    }
    

    类的循环引用

    使用weak例,定义了两个类:Person和Apartment,用来建模公寓和它其中的居民。Apartment的tenant属性被声明为弱引用以防止循环引用。

    class Person {
        let name: String
        init(name: String) { self.name = name }
        var apartment: Apartment?
        deinit { print("\(name) is being deinitialized") }
    }
    
    class Apartment {
        let unit: String
        init(unit: String) { self.unit = unit }
        weak var tenant: Person?
        deinit { print("Apartment \(unit) is being deinitialized") }
    }
    

    建立两个变量(john和unit4A)之间的强引用,并关联两个实例

    var john: Person?
    var unit4A: Apartment?
    
    john = Person(name: "John Appleseed")
    unit4A = Apartment(unit: "4A")
    
    john!.apartment = unit4A
    unit4A!.tenant = john
    

    使用unowned例,定义了两个类,Customer和CreditCard,模拟了银行客户和客户的信用卡。这两个类中,每一个都将另外一个类的实例作为自身的属性。这种关系可能会造成循环强引用。一个客户可能有或者没有信用卡,但是一张信用卡总是关联着一个客户,因此将customer属性定义为无主引用,用以避免循环强引用。

    class Customer {
        let name: String
        var card: CreditCard?
        init(name: String) {
            self.name = name
        }
        deinit { print("\(name) is being deinitialized") }
    }
    
    class CreditCard {
        let number: UInt64
        unowned let customer: Customer
        init(number: UInt64, customer: Customer) {
            self.number = number
            self.customer = customer
        }
        deinit { print("Card #\(number) is being deinitialized") }
    }
    

    建立两个变量(john和card)之间的强引用,并关联两个实例

    var john = Customer(name: "John Appleseed")
    john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
    

    (如有错误欢迎斧正)
    参考:
    极客学院自动引用计数
    swift中的delegate

    相关文章

      网友评论

          本文标题:swift防止循环引用简单整理

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