天天看點

Swift ARC機制以及弱引用的使用

  Swift使用自動引用計數(ARC)來管理應用程式的記憶體使用。當執行個體不再被需要時,由ARC自動釋放記憶體。swift ARC的機制通過編譯器實作,和java的gc垃圾回收機制不一樣。

  每當建立一個類的執行個體,ARC配置設定一個記憶體塊來存儲這個執行個體的資訊,包含了類型資訊和執行個體的屬性值資訊。ARC對每個類執行個體,都追蹤有多少屬性、常量、變量指向這些執行個體。當有活動引用指向它時,ARC是不會釋放這個執行個體的。當執行個體不再被使用時,ARC會釋放執行個體所占用的記憶體,這些記憶體可以再次被使用。

  下面的測試程式,testARC1 記憶體釋放比函數結束先進行,說明在引用計數為0時,記憶體會立即釋放。testARC2,說明在存在循環引用時,使用弱引用可以防止記憶體洩漏,因為弱引用并不保持對所指對象的強烈持有,是以并不阻止ARC對引用執行個體的回收。指明弱引用需添加weak關鍵字。

具體代碼:

//
//  main.swift
//  ARCTest
//
//  Created by 淩雲 on 16/1/12.
//  Copyright © 2016年 淩雲. All rights reserved.
//

import Foundation

class Teacher
{
    var storeName:String //存儲屬性
    var name:String{//計算屬性
        get{
            return self.storeName
        }
        set{
            self.storeName = newValue//便捷setter聲明
        }
    }

    var student: Student?//可選類型不用在init函數中初始化

    init(name:String)
    {
        storeName = name
        print("老師\(self.name)執行個體初始化完成")
    }

    deinit
    {
        print("老師\(name)執行個體記憶體釋放")
    }

    func teaching()
    {
        print("老師\(name)正在講課")
    }
}

class Student
{
    var storeName:String //存儲屬性
    var name:String{//計算屬性
        get{
            return self.storeName
        }
        set{
            self.storeName = newValue//便捷setter聲明
        }
    }

    weak var teacher: Teacher? //弱引用,解決互相引用導緻的記憶體洩露問題

    init(name:String)
    {
        storeName = name
        print("學生\(self.name)執行個體初始化完成")
    }

    deinit
    {
        print("學生\(name)執行個體記憶體釋放")
    }

    func learning()
    {
        print("學生\(name)正在聽課")
    }

}

func testARC1()
{
    var teacher:Teacher? = Teacher(name:"張先生")//使用可選類型以後面指派為nil
    var teacher2:Teacher? = teacher
    var teacher3:Teacher? = teacher2
    teacher?.teaching()
    teacher2?.teaching()
    teacher3?.teaching()

    teacher = nil
    teacher2 = nil
    teacher3 = nil//第三個引用對象為nil,此時已無引用,arc回收,執行個體釋放

    print("\(teacher?.teaching())")//可選類型,已釋放調用也不會崩潰

    print("test arc1 end.")
}

func testARC2()
{
    var teacher:Teacher? = Teacher(name:"Zhang先生")
    var student:Student? = Student(name:"Xiao學生")
    teacher?.teaching()
    student?.learning()

    teacher?.student = student
    student?.teacher = teacher

    teacher = nil
    student = nil

    print("test arc2 end.")
}

testARC1()
testARC2()
print("程式結束.")

           

運作結果:

老師張先生執行個體初始化完成

老師張先生正在講課

老師張先生正在講課

老師張先生正在講課

老師張先生執行個體記憶體釋放

nil

test arc1 end.

老師Zhang先生執行個體初始化完成

學生Xiao學生執行個體初始化完成

老師Zhang先生正在講課

學生Xiao學生正在聽課

老師Zhang先生執行個體記憶體釋放

學生Xiao學生執行個體記憶體釋放

test arc2 end.

程式結束.

可以看到,testARC2在存在循環引用的情況下,仍然成功的進行了記憶體釋放。

參考資料:

[1]: http://blog.csdn.net/fengsh998/article/details/31824179 “fengsh998”