免费开源的iOS开发学习平台

Swift:16 析构

在类实例释放之前,析构器(deinitializer)会被立即调用。和使用init关键词来声明构造器一样,使用deinit关键词来声明析构器。析构器只能在类类型中声明。

析构原理

Swift会自动释放不再需要使用的实例,从而让资源得到回收。Swift通过自动引用计数(ARC)来管理实例内存。通常在释放实例资源时不需要手动清理,但使用自定义的资源时,就可能需要额外的清理操作。比如你创建了一个自定义的类来打开并且写入一个文件,你可能需要在类实例被释放前关闭这个文件。

在类的定义中,每个类最多只能有一个析构器。析构器不接收任何形参,并且不带圆括号:

deinit{
    //析构代码
}

析构器在实例释放发生前被自动调用,不允许主动调用析构器。子类继承了超类的析构器,在定义子类析构器的最后自动调用超类的析构器。即使子类没有提供自己的析构器,超类的析构器也还是会被调用。

示例

下面示例声明了一个Store仓库类来存储所有的金币,Store仓库的金币总数是固定的,通过Store的distribute(golds required:Int)方法来发放金币。Player玩家初始化会有一定的金币数,通过win(golds:Int)方法来获取更多的金币。通过声明Player的可选类型,这样就可以手动的释放player这个类实例,一旦player被释放,就会自动执行deinit,把player中的金币归还给Store仓库。

class Store {
    static var totalGolds = 10_000
    static func distribute(golds required: Int)->Int{
        let shoulded = min(required,totalGolds)
        totalGolds -= shoulded
        return shoulded
    }
    
    static func receive(coins:Int){
        totalGolds += coins
    }
}

class Player{
    var golds:Int
    init(golds:Int) {
        self.golds = Store.distribute(golds: golds)
    }
    func win(golds:Int)  {
        self.golds += Store.distribute(golds: golds)
    }
    deinit {
        Store.receive(coins: golds)
    }
}

var player:Player? = Player(golds: 100)

print("玩家初始化金币数为:\(player!.golds)")

print("仓库中还剩余金币数:\(Store.totalGolds)")

player!.win(golds: 2000)

print("玩家现在金币数为:\(player!.golds)")

print("仓库中还剩余金币数:\(Store.totalGolds)")

player = nil

print("仓库中现在金币数:\(Store.totalGolds)")

代码执行结果截图如下。

示例代码

https://github.com/99ios/23.17