//
// MemoryManagement.swift
// SwiftCode
//
// Created by Alisa on 2022/4/10.
// Copyright © 2022 Alisa. All rights reserved.
//
import Foundation
/*
**循环引用
swift的实例在内存中的引用计数,与oc中的很像,只是多了一个无主引用
造成循环引用的原因:A持有了B,B持有了A,当内存需要释放时,A在等B释放,B在等A释放,最后两者都没有被释放
weak关键字处理循环引用:weak关键字的作用是在使用这个实例的时候并不保有此实例的引用,普通的引用类型数据在传递时会使实例的引用计数加1,使用weak
关键字修饰的引用类型数据在传递时不会使引用计数加1.
在使用weak弱引用时,需要注意:其职能职能修饰optional类型的属性,被弱引用的实例释放后,这个属性会被自动设置为nil
unowned:对于非optional值类型的属性,可以使用unowned属性去处理循环引用的问题。
无主引用在修饰实例时,不会使引用计数加1,无主引用保证其引用的实例不为nil,当无主引用断开时,引用计数也不会-1
无主引用与隐式拆包语法相结合可以使两个类中互相引用的属性都是非Optional值,这也是无主引用最佳的使用场景
**weak与unowned的区别:
<1>weak只用于修饰optional的值,unowned用于修饰非optional的值
<2>weak修饰的属性允许属性的值为nil,unowned修饰的属性假定不为nil
<3>unowned与隐式拆包语法相结合使用,weak与optional的特性结合使用
<4>unowned常用于处理闭包的循环引用问题
**闭包中的循环引用:
在一个类中,如果其有属性为闭包,则也可能产生类与属性之间的相互引用
闭包造成引用计数的原因: 闭包是一种特殊的语法结构,在其中使用的引用类型的实例都会使引用计数+1,因此如果在闭包中使用self关键字,会对当前类实例本身引用计数+1
由于此闭包又是当前类的一个属性,闭包属性无法销毁,当前类实例也就无法销毁。反过来当前实例无法销毁,闭包也无法销毁,造成循环引用了。
闭包循环引用问题的处理:
系统专门为闭包结构提供了捕获列表,来对闭包内使用的变量或者实例进行弱引用或无主引用的转换
捕获列表在结构上需要紧跟在闭包的起始大括号后,使用中括号包围
*/
//使用weak关键字处理循环引用
class Scissors{
weak var hammer:Hammer?
var weight:Float
init(weight:Float) {
self.weight = weight
}
deinit{
print("This is scissors deinit!")
}
}
class Hammer{
weak var scissors:Scissors?
var weight:Float
init(weight:Float) {
self.weight = weight
}
deinit{
print("This is hammer deinit!")
}
}
//使用unowned关键字处理循环引用
class Stone{
//不是optional值,不能进行弱引用
unowned var sand:Sand
var name:String
lazy var weight:Float = 0.0
init(sand:Sand, name:String) {
self.sand = sand
self.name = name
}
deinit{
print("This is Stone deinit!")
}
}
class Sand{
//这里使用隐式拆包的方式
var stone:Stone!
var name:String
init(name:String) {
self.name = name
}
deinit{
print("This is Sand deinit!")
}
}
//闭包中的循环引用
class Rivers{
var color:String
lazy var flowBeautiful:()->Void = {
//使用捕获列表对闭包中使用到self进行无主引用的转换
[unowned self]()->Void in
print("The rivers flow very beautiful!, and this river color is: \(self.color)")
}
init(color:String) {
self.color = color
}
deinit{
print("This is Rivers deinit!")
}
}
class MemoryManagement{
//使用weak关键字处理循环引用
func useWeak(){
let scissors = Scissors(weight: 22.0)
let hammer = Hammer(weight: 10.0)
scissors.hammer = hammer
hammer.scissors = scissors
/*当离开当前函数的作用域时,打印信息如下:
This is hammer deinit!
This is scissors deinit!
*/
}
//使用unowned关键字处理循环引用
func useUnowned(){
let sand = Sand(name: "sand one")
let stone = Stone(sand: sand, name: "stone one")
stone.weight = 2200.0
/*当离开当前函数的作用域时,打印信息如下:
This is Stone deinit!
This is Sand deinit!
*/
}
//闭包中的循环引用
func useClosure(){
var river:Rivers? = Rivers(color: "blue color")
river?.flowBeautiful();
river = nil
/* 打印信息如下:
The rivers flow very beautiful!, and this river color is: blue color 调用闭包时打印的
This is Rivers deinit! 当river实例被置为nil时,调用了析构函数deinit
*/
}
}
Swift 内存管理
最新推荐文章于 2023-02-24 15:30:09 发布