swift析构过程和自动引用计数(ARC) – Swift最新教程

上一章Swift教程请查看:swift类、结构体和枚举的初始化

本章我们讨论swift中的析构过程,使用deinit实现,以及swift中的自动引用计数(ARC)。

Swift析构过程

在需要释放类实例之前,必须调用“deinitializer”来释放内存空间。关键字“deinit”用于释放系统资源占用的内存空间,析构仅对类类型可用。

释放内存空间的析构过程

当不再需要实例时,Swift
会自动释放它们,以释放资源。Swift 通过自动引用计数(ARC)处理实例的内存管理,如自动引用计数中所述。通常,在释放实例时不需要执行手动清理。然而,当你使用自己的资源时,你可能需要自己执行一些额外的清理工作。例如,如果你创建一个自定义类来打开一个文件并向其写入一些数据,那么你可能需要在释放类实例之前关闭该文件。

var counter = 0; // 用于引用计数
class baseclass {
   init() {
      counter++;
   }
   deinit {
      counter--;
   }
}
var print: baseclass? = baseclass()

print(counter)
print = nil
print(counter)

当print = nil语句被省略时,计数器的值保持不变,因为它没有被取消初始化。

var counter = 0; // 用于引用计数

class baseclass {
   init() {
      counter++;
   }
   deinit {
      counter--;
   }
}
var print: baseclass? = baseclass()
print(counter)
print(counter)

自动引用计数(ARC)

在Swift 语言中内存管理功能及其使用通过自动引用计数(ARC)处理,ARC用于初始化和初始化系统资源,从而在不再需要类实例时释放类实例使用的内存空间。ARC跟踪代码实例之间关系的信息,以有效地管理内存资源。

ARC的功能

  • 每次init()创建一个新的类实例时,ARC都会分配一块内存来存储这些信息。
  • 关于实例类型及其值的信息存储在内存中。
  • 当不再需要类实例时,它会通过deinit()自动释放内存空间,以便进一步存储和检索类实例。
  • ARC跟踪当前引用的类实例属性、常量和变量,以便deinit()只应用于那些未使用的实例。
  • ARC维护对类实例属性、常量和变量的“强引用”,以在类实例当前使用时限制释放位置。

ARC程序

class StudDetails {
    var stname: String!
    var mark: Int!
    
    init(stname: String, mark: Int) {
       self.stname = stname
       self.mark = mark
    }
    deinit {
       print("释放 \(self.stname)")
       print("释放 \(self.mark)")
    }
 }
 
 let stname = "Swift"
 let mark = 98
 
 print(stname)
 print(mark)

ARC强引用循环类实例

class studmarks {
    let name: String
    var stud: student?
    
    init (name: String) {
       print("初始化: \(name)")
       self.name = name
    }
    deinit {
       print("释放内存: \(self.name)")
    }
 }
 
 class student {
    let name: String
    var strname: studmarks?
    
    init (name: String) {
       print("初始化: \(name)")
       self.name = name
    }
    deinit {
       print("释放内存: \(self.name)")
    }
 }
 
 var shiba: studmarks?
 var mari: student?
 
 shiba = studmarks(name: "Swift")
 mari = student(name: "ARC")
 
 shiba!.stud = mari
 mari!.strname = shiba

弱引用和无主引用

类类型属性有两种方法来解析强引用循环

  • 弱引用
  • 无主引用

这些引用用于使一个实例能够引用引用循环中的其他实例,然后实例可能引用每一个实例,而不是关心强引用周期。当用户知道某个实例可能会返回’nil’值时,我们可以使用弱引用来指出这一点。当实例要返回一些东西而不是nil时,就用无主引用声明它。

弱引用程序

class module {
    let name: String
    init(name: String) { self.name = name }
    var sub: submodule?
    deinit { print("\(name) 主模块") }
 }
 
 class submodule {
    let number: Int
    init(number: Int) { self.number = number }
    weak var topic: module?
 
    deinit { print("子模块的number为 \(number)") }
 }
 
 var toc: module?
 var list: submodule?
 toc = module(name: "ARC")
 list = submodule(number: 4)
 toc!.sub = list
 list!.topic = toc
 
 toc = nil
 list = nil

无主引用程序

class student {
    let name: String
    var section: marks?
    init(name: String) {
       self.name = name
    }
    deinit { print("\(name)") }
 }
 
 class marks {
    let marks: Int
    unowned let stname: student
    
    init(marks: Int, stname: student) {
       self.marks = marks
       self.stname = stname
    }
    deinit { print("分数: \(marks)") }
 }
 
 var module: student?
 module = student(name: "ARC")
 module!.section = marks(marks: 98, stname: module!)

闭包的强引用周期

当我们将闭包分配给类实例属性和闭包体以捕获特定实例时,可能会发生强引用循环。强引用闭包由‘self’定义。someProperty’或‘self.someMethod ()”,强引用循环用作闭包的引用类型。

class HTMLElement {
    let samplename: String
    let text: String?
    
    lazy var asHTML: () -> String = {
       if let text = self.text {
          return "<\(self.samplename)>\(text)</\(self.samplename)>"
       } else {
          return "<\(self.samplename) />"
       }
    }
    init(samplename: String, text: String? = nil) {
       self.samplename = samplename
       self.text = text
    }
    deinit {
       print("\(samplename) 被释放")
    }
 }
 
 var paragraph: HTMLElement? = HTMLElement(samplename: "p", text: "闭包SRC")
 print(paragraph!.asHTML())

弱引用和无主引用

当闭包和实例相互引用时,用户可以将闭包中的捕获定义为无主引用。然后它将不允许用户同时释放实例,当实例有时返回一个“nil”值时,使用弱实例定义闭包。

class HTMLElement {
    let module: String
    let text: String?
    
    lazy var asHTML: () -> String = {
       [unowned self] in
       if let text = self.text {
          return "<\(self.module)>\(text)</\(self.module)>"
       } else {
          return "<\(self.module) />"
       }
    }
    init(module: String, text: String? = nil) {
       self.module = module
       self.text = text
    }
    deinit {
       print("\(module) deinit()")
    }
 }
 
 var paragraph: HTMLElement? = HTMLElement(module: "Inside", text: "ARC弱引用")
 print(paragraph!.asHTML())
 paragraph = nil
微信公众号
手机浏览(小程序)
0
分享到:
没有账号? 忘记密码?