析构过程
析构器只适用于类类型,当一个类的实例被释放之前,析构器会被立即调用。析构器用关键字deinit
来标示,类似于构造器要用init
来标示。
原理
Swift 会自动释放不再需要的实例以释放资源,Swift 通过自动引用计数(ARC)
处理实例的内存管理。通常当你的实例被释放时不需要手动地去清理。但是,当使用自己的资源时,你可能需要进行一些额外的清理。例如,如果创建了一个自定义的类来打开一个文件,并写入一些数据,你可能需要在类实例被释放之前手动去关闭该文件。
deinit {
// 在这里实现析构过程
}
析构器是在实例释放发生前被自动调用。析构器是不允许被主动调用的。子类继承了父类的析构器,并且在子类析构器实现的最后,父类的析构器会被自动调用。即使子类没有提供自己的析构器,父类的析构器也同样会被调用。
因为直到实例的析构器被调用时,实例才会被释放,所以析构器可以访问所有请求实例的属性,并且根据那些属性可以修改它的行为(比如查找一个需要被关闭的文件)。
操作演示
// 游戏币中心 结构体
struct Bank {
static var coinsInBank = 10_000 // 虚拟游戏币
// 出售游戏币
static func vendCoins(numberOfCoinsToVend: Int) -> Int {
let coinsToVend = min(numberOfCoinsToVend, coinsInBank)
coinsInBank -= coinsToVend
return numberOfCoinsToVend
}
// 回收游戏币
static func receiveCoins(coins: Int) {
coinsInBank += coins
}
}
// 玩家类
class Player {
var coinsInPurse: Int
init(coins: Int) {
// 构造方法中调用了Bank的类型方法,来获得游戏币,并且数量控制在10,000以内。
coinsInPurse = Bank.vendCoins(coins)
}
func winCoins(coins: Int) {
// 赢得游戏币方法,从Bank中获得游戏币
coinsInPurse += Bank.vendCoins(coins)
}
deinit {
// 当玩家被释放时需要将所有游戏币归还到Bank
Bank.receiveCoins(coinsInPurse)
}
}
// 这里将playerOne设置为可选属性,因为playerOne随时会被制为nil
var playerOne: Player? = Player(coins: 3000)
// player 3000 Bank 7000
print("playerOne coins:\(playerOne!.coinsInPurse), Bank coins: \(Bank.coinsInBank)")
playerOne?.winCoins(500)
// player 3500 Bank 6500
print("playerOne coins:\(playerOne!.coinsInPurse), Bank coins: \(Bank.coinsInBank)")
// 将playerOne制为空,没有任何引用指向playerOne内存,ARC机制会自动释放这块内存,deinit方法被调用,归还游戏币
playerOne = nil
// Bank 10000
print("Bank coins: \(Bank.coinsInBank)")