- Swift 教程
- Swift - 首页
- Swift - 概述
- Swift - 环境
- Swift - 基本语法
- Swift - 变量
- Swift - 常量
- Swift - 字面量
- Swift - 注释
- Swift 运算符
- Swift - 运算符
- Swift - 算术运算符
- Swift - 比较运算符
- Swift - 逻辑运算符
- Swift - 赋值运算符
- Swift - 位运算符
- Swift - 其他运算符
- Swift 高级运算符
- Swift - 运算符重载
- Swift - 算术溢出运算符
- Swift - 恒等运算符
- Swift - 范围运算符
- Swift 数据类型
- Swift - 数据类型
- Swift - 整数
- Swift - 浮点数
- Swift - Double
- Swift - 布尔值
- Swift - 字符串
- Swift - 字符
- Swift - 类型别名
- Swift - 可选类型
- Swift - 元组
- Swift - 断言和前提条件
- Swift 控制流
- Swift - 决策
- Swift - if 语句
- Swift - if...else if...else 语句
- Swift - if-else 语句
- Swift - 嵌套 if 语句
- Swift - switch 语句
- Swift - 循环
- Swift - for in 循环
- Swift - while 循环
- Swift - repeat...while 循环
- Swift - continue 语句
- Swift - break 语句
- Swift - fall through 语句
- Swift 集合
- Swift - 数组
- Swift - 集合
- Swift - 字典
- Swift 函数
- Swift - 函数
- Swift - 嵌套函数
- Swift - 函数重载
- Swift - 递归
- Swift - 高阶函数
- Swift 闭包
- Swift - 闭包
- Swift - 转义和非转义闭包
- Swift - 自动闭包
- Swift 面向对象编程
- Swift - 枚举
- Swift - 结构体
- Swift - 类
- Swift - 属性
- Swift - 方法
- Swift - 下标
- Swift - 继承
- Swift - 重写
- Swift - 初始化
- Swift - 析构
- Swift 高级
- Swift - ARC 概述
- Swift - 可选链
- Swift - 错误处理
- Swift - 并发
- Swift - 类型转换
- Swift - 嵌套类型
- Swift - 扩展
- Swift - 协议
- Swift - 泛型
- Swift - 访问控制
- Swift - 函数与方法
- Swift - SwiftyJSON
- Swift - 单例类
- Swift 随机数
- Swift 不透明类型和装箱类型
- Swift 有用资源
- Swift - 在线编译
- Swift - 快速指南
- Swift - 有用资源
- Swift - 讨论
Swift - ARC 概述
Swift 中的自动引用计数
自动引用计数 (ARC) 是 Swift 使用的一种内存管理机制,它自动跟踪和管理对象的内存分配和释放。或者我们可以说它用于初始化和反初始化系统资源,从而在不再需要类实例时释放类实例使用的内存空间。它跟踪实例之间关系的信息,以有效地管理内存资源。ARC 通常仅适用于类的实例,因为它们是引用类型。
ARC 的工作原理
每当通过 init() 创建新的类实例时,ARC 都会分配一块内存来存储信息。
实例类型及其值的相关信息存储在内存中。
当不再需要类实例时,它会通过 deinit() 自动释放内存空间,以便进一步存储和检索类实例。
ARC 跟踪当前引用的类实例属性、常量和变量,以便仅对未使用的实例应用 deinit()。
ARC 对这些类实例属性、常量和变量保持“强引用”,以限制在类实例当前正在使用时进行释放。
示例
演示 ARC 的 Swift 程序。
class StudDetails {
// Properties
var stname: String
var mark: Int
// Initializer to initialize instances of the class
init(stname: String, mark: Int) {
self.stname = stname
self.mark = mark
}
// Deinitializer to deinitialize the instances of
// the class when they are no longer required
deinit {
print("Deinitialized \(self.stname)")
print("Deinitialized \(self.mark)")
}
}
// Creating class instance
var obj1 = StudDetails( stname:"Swift", mark:98)
// Creating another class instance
var obj2: StudDetails? = StudDetails(stname: "iOS", mark: 95)
// Setting anotherObj to nil to deallocate the memory
obj2 = nil
输出
它将产生以下输出:
Deinitialized iOS Deinitialized 95
Swift 中类实例之间的强引用循环
ARC 用于通过跟踪对象引用来自动管理内存。但是,开发人员面临着一个挑战,那就是创建强引用循环,其中两个或多个对象相互强引用,这会阻止它们的引用计数达到零,并且由于此原因会导致内存泄漏。
示例
演示 Swift 中类实例之间强引用循环的 Swift 程序。
class studmarks {
let name: String
var stud: student?
// Initializer
init (name: String) {
print("Initializing: \(name)")
self.name = name
}
// Deinitializer
deinit {
print("Deallocating: \(self.name)")
}
}
class student {
let name: String
var strname: studmarks?
// Initializer
init (name: String) {
print("Initializing: \(name)")
self.name = name
}
// Deinitializer
deinit {
print("Deallocating: \(self.name)")
}
}
// Declare optional variables for instances
var shiba: studmarks?
var mari: student?
shiba = studmarks(name: "Swift 4")
mari = student(name: "ARC")
// Create a strong reference cycle by assigning references to each other
shiba!.stud = mari
mari!.strname = shiba
输出
它将产生以下输出:
Initializing: Swift 4 Initializing: ARC
为了解决强引用循环,Swift 提供了弱引用和无主引用。这些引用用于使一个实例能够引用引用循环中的其他实例。然后,实例可以引用每个实例,而不必关心强引用循环。
弱引用
它对对象的引用是可选的,并且不会对该对象进行强引用。当它引用的对象被释放时,它将返回 nil。它通常用于引用的对象的生命周期不保证比引用对象持续时间更长的情况。它通常用于引用的对象可以独立释放的关系。我们可以使用weak关键字声明弱引用。
语法
以下是弱引用的语法:
class Class1 {
var name: Name?
}
class Name {
weak var teacher: Class1?
}
示例
演示弱引用的 Swift 程序。
class module {
let name: String
init(name: String) { self.name = name }
var sub: submodule?
deinit { print("\(name) Is The Main Module") }
}
class submodule {
let number: Int
init(number: Int) { self.number = number }
weak var topic: module?
deinit { print("Sub Module with its topic number is \(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
输出
它将产生以下输出:
ARC Is The Main Module Sub Module with its topic number is 4
无主引用
与弱引用相比,它对对象的引用是非可选的,并且不会对该对象进行强引用。它假设引用对象永远不会变成 nil,而引用对象仍然存在。它通常用于您知道引用的对象的生命周期至少与引用对象的生命周期一样长的情况。它通常用于引用的对象与引用对象具有相同或更长的生命周期的关系。我们可以使用unowned关键字声明无主引用。
语法
以下是无主引用的语法:
class Class1 {
var name: Name?
}
class Name {
unowned var teacher: Class1
}
示例
演示无主引用的 Swift 程序。
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 Obtained by the student is \(marks)") }
}
var module: student?
module = student(name: "ARC")
module!.section = marks(marks: 98, stname: module!)
module = nil
输出
它将产生以下输出:
ARC Marks Obtained by the student is 98
闭包的强引用循环
当我们将闭包分配给类实例属性并将闭包的主体捕获特定实例时,可能会发生强引用循环。对闭包的强引用由“self.someProperty”或“self.someMethod()”定义。强引用循环用作闭包的引用类型。
示例
演示闭包的强引用循环的 Swift 程序。
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) is being deinitialized")
}
}
var paragraph: HTMLElement? = HTMLElement(samplename: "p", text: "Welcome to Closure SRC")
print(paragraph!.asHTML())
输出
它将产生以下输出:
<p>Welcome to Closure SRC</p>
解决闭包的强引用循环
我们可以使用弱引用和无主引用来解决闭包的强引用循环。当闭包和实例相互引用时,用户可以将闭包中的捕获定义为无主引用。然后它将不允许用户同时释放实例。当实例有时返回“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) the deinit()")
}
}
var paragraph: HTMLElement? = HTMLElement(module: "Inside", text: "ARC Weak References")
print(paragraph!.asHTML())
paragraph = nil
输出
它将产生以下输出:
<Inside>ARC Weak References</Inside> Inside the deinit()