美文网首页
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