美文网首页
iOS 开发 ARC(自动引用计数器)swift

iOS 开发 ARC(自动引用计数器)swift

作者: FrancisYin | 来源:发表于2016-06-20 00:08 被阅读0次

    参考Swift Program Language

    基础知识

    对象分为三种引用类方式 分别为 strong weak unowned 对象默认引用方式为 strong。strong 对象赋值时引用计数器加一 weak 和 unowned 对象赋值时引用计数器值不变,weak 类型定义时必须是optional 或者是 强制解包类型,unowned 对象必须要有默认值。
    swift 闭包(closure)中定义在closure 外的对象引用计数器自动加一。

    循环引用

    weak引用

    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 }
      var tenant: Person?
      deinit { print("Apartment \(unit) is being deinitialized") }
    }
    
    var john: Person?
    
    var unit4A: Apartment?
    
    john = Person(name: "John Appleseed")
    unit4A = Apartment(unit: "4A")
    //图一
    
    john!.apartment = unit4A
    unit4A!.tenant = john
    //图二
    
    图1图1
    图2图2

    当设置 john 与 unit4A 为nil 时 john 和 unit4A 引用计数器都是1 对象不会被删除。

    john = nil
    unit4A = nil
    
    图3图3

    解决方案

    在类定义时外部引用的成员变量设置成weak

    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") }
    }
    var john: Person?
    var unit4A: Apartment?
    
    john = Person(name: "John Appleseed")
    unit4A = Apartment(unit: "4A")
    
    john!.apartment = unit4A
    unit4A!.tenant = john
    //图4
    
    图4图4
    john = nil
    //图5
    
    图5图5
    unit4A = nil
    //图6
    
    图6图6

    unowned 引用

    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") }
    }
    
    var john: Customer?
    john = Customer(name: "John Appleseed")
    john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
    //图7
    
    图7图7
    john = nil
    //图8
    
    图8图8

    john 对象设置为nil ,john引用计数器为0 john被析构,john.card引用计数器也为0 john 也被析构。

    闭包引起的强引用循环

    class HTMLElement {
        let name: String
        let text: String?
        lazy var asHTML: () -> String = {
        if let text = self.text {
          return "<\(self.name)>\(text)</\(self.name)>"
        } else {
          return "<\(self.name) />"
        }
      }
      init(name: String, text: String? = nil) {
        self.name = name
        self.text = text
      }
      deinit {
        print("\(name) is being deinitialized")
      }
    }
    let heading = HTMLElement(name: "h1")
    let defaultText = "some default text"
    heading.asHTML = {
      return "<\(heading.name)>\(heading.text ?? defaultText)</\(heading.name)>"
    }
    print(heading.asHTML())
    
    var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world")
    print(paragraph!.asHTML())
    //closure 使用 closure 外部的对象时 外部对象的引用计数器+1
    //图9
    
    图9图9

    解决方案

    //定义closure时
    lazy var asHTML: () -> String = {[weak self] in
        if let text = self.text {
          return "<\(self.name)>\(text)</\(self.name)>"
        } else {
          return "<\(self.name) />"
        }
      }
    //或者
    lazy var asHTML: () -> String = {[unowned self] in
        if let text = self.text {
          return "<\(self.name)>\(text)</\(self.name)>"
        } else {
          return "<\(self.name) />"
        }
      }
    

    unowned 与weak 的区别
    上面的例子 如果设置为weak 当外部的对象self 在closure内是一个optional 类型 设置为unowned closure 内部维持原状
    对象内部的closure 的生命周期比对象本身的周期时间长 建议不要使用unowned 使用weak

    相关文章

      网友评论

          本文标题:iOS 开发 ARC(自动引用计数器)swift

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