欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

實(shí)例講解Swift中引用類型的ARC自動(dòng)引用計(jì)數(shù)

 更新時(shí)間:2016年07月07日 18:21:08   作者:琿少  
自動(dòng)引用計(jì)數(shù)是在Objective-C中就有的特性,用來輔助管理對(duì)象的引用,這里我們就來以實(shí)例講解Swift中引用類型的ARC自動(dòng)引用計(jì)數(shù):

一、引言

ARC(自動(dòng)引用計(jì)數(shù))是Objective-C和Swift中用于解決內(nèi)存管理問題的方案。在學(xué)習(xí)Objective-C編程時(shí)經(jīng)常會(huì)學(xué)習(xí)到一個(gè)關(guān)于ARC的例子:在一個(gè)公用的圖書館中,每次進(jìn)入一人就將卡插入,走的時(shí)候?qū)⒆约旱目ò纬瞿米?。圖書館系統(tǒng)會(huì)判定只要有卡插入,就將圖書館的燈打開,當(dāng)所有卡都被取走后,將圖書館的燈關(guān)掉。這個(gè)例子對(duì)應(yīng)于Objective-C中的對(duì)象聲明周期管理十分貼切。每當(dāng)一個(gè)對(duì)象增加一個(gè)引用時(shí),其引用計(jì)數(shù)會(huì)加1,當(dāng)一個(gè)引用被取消時(shí),對(duì)象的引用計(jì)數(shù)減1,當(dāng)引用計(jì)數(shù)減為0時(shí),說明此對(duì)象將不再有任何引用,對(duì)象會(huì)被釋放掉,讓出內(nèi)存。Swift也采用同樣的方式進(jìn)行內(nèi)存管理。

注意:在Swift中只有引用類型有自動(dòng)引用計(jì)數(shù),結(jié)構(gòu)體、枚舉這類值類型是沒有引用計(jì)數(shù)的。關(guān)于引用計(jì)數(shù)的示例代碼如下:

class MyClass {
  deinit{
    print("MyClass deinit")
  }
}
var cls1:MyClass? = MyClass()
var cls2:MyClass? = cls1
var cls3:MyClass? = cls2
cls2 = nil
cls1 = nil
//執(zhí)行下面代碼后才會(huì)打印“MyClass deinit”
cls3 = nil

二、循環(huán)引用的處理方法

在開發(fā)中,開發(fā)者一不小心就會(huì)寫出產(chǎn)生循環(huán)引用的代碼,在上面的示例中可以看出,除非實(shí)例的引用全部解除,否則實(shí)例將不會(huì)調(diào)用析構(gòu)方法,內(nèi)存不會(huì)被釋放,如果在寫代碼時(shí),A引用了B,同樣B也引用了A,那么實(shí)際上現(xiàn)在A和B的引用計(jì)數(shù)都是2,將A和B都置為nil后,A和B實(shí)例依然保有1個(gè)引用計(jì)數(shù),都不會(huì)被釋放,實(shí)例如下:

class MyClassOne {
  var cls:MyClassTwo?
  deinit{
    print("ClassOne deinit")
  }
}
class MyClassTwo {
  var cls:MyClassOne?
  deinit{
    print("ClassTwo deinit")
  }
}
var obj1:MyClassOne? = MyClassOne()
var obj2:MyClassTwo? = MyClassTwo()
obj1?.cls = obj2
obj2?.cls = obj1
obj1=nil
obj2=nil
//沒有打印析構(gòu)函數(shù)的調(diào)用信息

對(duì)于上面的情況,可以將屬性聲明稱weak類型來防止這種循環(huán)引用,weak的作用在于只是弱引用實(shí)例,原實(shí)例的引用計(jì)數(shù)并不會(huì)加1,示例如下:

//關(guān)于弱引用的演示
class MyClassThree{
  weak var cls:MyClassFour?
  deinit{
    print("ClassThree deinit")
  }
}
class MyClassFour {
  var cls:MyClassThree?
  deinit{
    print("ClassFour deinit")
  }
}
var obj3:MyClassThree? = MyClassThree()
var obj4:MyClassFour? = MyClassFour()
obj3?.cls = obj4
obj4?.cls = obj3
obj4=nil
//此時(shí)obj3中的cls也為nil
obj3?.cls

若引用的實(shí)例被釋放后,其在另一個(gè)實(shí)例中的引用也將被置為nil,所以weak只能用于optional類型的屬性,然而在開發(fā)中還有一種情況,某個(gè)類必須保有另一個(gè)類的示例,這個(gè)實(shí)例不能為nil,但是這個(gè)屬性又不能影響其原始實(shí)例的釋放,這種情況也會(huì)造成循環(huán)引用,示例如下:

class MyClassFive{
  var cls:MyClassSix
  init(param:MyClassSix){
    cls = param
  }
  deinit{
    print("ClassFive deinit")
  }
}
class MyClassSix{
  var cls:MyClassFive?
  deinit{
    print("ClassSix deinit")
  }
}
var obj6:MyClassSix? = MyClassSix()
var obj5:MyClassFive? = MyClassFive(param: obj6!)
obj6?.cls = obj5
obj5=nil
obj6=nil
//沒有打印任何信息

上面的示例也會(huì)造成循環(huán)引用,然而MyClassFive類中的cls屬性為常量不可為nil,不可使用weak弱引用來做Swift中又提供了一個(gè)關(guān)鍵字unowned無(wú)主引用來處理這樣的問題,示例如下:

class MyClassFive{
  unowned var cls:MyClassSix
  init(param:MyClassSix){
    cls = param
  }
  deinit{
    print("ClassFive deinit")
  }
}
class MyClassSix{
  var cls:MyClassFive?
  deinit{
    print("ClassSix deinit")
  }
}
var obj6:MyClassSix? = MyClassSix()
var obj5:MyClassFive? = MyClassFive(param: obj6!)
obj6?.cls = obj5
obj5=nil
obj6=nil

關(guān)于弱引用和無(wú)主引用,其區(qū)別主要是在于:

1.弱引用用于解決Optional值的引起的循環(huán)引用。

2.無(wú)主引用用于解決非Optional值引起的循環(huán)引用。

3.個(gè)人以為,弱引用可用下圖表示:

201677181603163.png (1516×724)

4.無(wú)主引用可用如下圖表示:

201677181654671.jpg (1516×724)

若將上面的代碼修改如下,程序會(huì)直接崩潰:

class MyClassFive{
  unowned var cls:MyClassSix
  init(param:MyClassSix){
    cls = param
  }
  deinit{
    print("ClassFive deinit")
  }
}
class MyClassSix{
  var cls:MyClassFive?
  deinit{
    print("ClassSix deinit")
  }
}
var obj6:MyClassSix? = MyClassSix()
var obj5:MyClassFive? = MyClassFive(param: obj6!)
obj6?.cls = obj5
obj6=nil
obj5?.cls

上面所舉的例子滿足了兩種情況,一種是兩類實(shí)例引用的屬性都是Optional值的時(shí)候使用weak來解決循環(huán)引用,一種是兩類實(shí)例有一個(gè)為非Optional值的時(shí)候使用unowned來解決循環(huán)引用,然而還有第三種情況,兩類實(shí)例引用的屬性都為非Optional值的時(shí)候,可以使用無(wú)主引用與隱式拆包結(jié)合的方式來解決,這也是無(wú)主引用最大的應(yīng)用之處,示例如下:

class MyClassSeven{
  unowned var cls:MyClassEight
  init(param:MyClassEight){
    cls = param
  }
  deinit{
    print("ClassSeven deinit")
  }
}
class MyClassEight{
  var cls:MyClassSeven!
  init(){
    cls = MyClassSeven(param:self)
  }
  deinit{
    print("ClassEight deinit")
  }
}
var obj7:MyClassEight? = MyClassEight()
obj7=nil

除了在兩個(gè)類實(shí)例間會(huì)產(chǎn)生循環(huán)引用,在閉包中,也可能出現(xiàn)循環(huán)引用,當(dāng)某個(gè)類中包含一個(gè)閉包屬性,同時(shí)這個(gè)閉包屬性中又使用了類實(shí)例,則會(huì)產(chǎn)生循環(huán)引用,示例如下:

class MyClassNine {
  var name:String = "HS"
  lazy var closure:()->Void = {
    //閉包中使用引用值會(huì)使引用+1
    print(self.name)
  }
  deinit{
    print("ClassNine deinit")
  }
}
var obj9:MyClassNine? = MyClassNine()
obj9?.closure()
obj9=nil
//不會(huì)打印析構(gòu)信息

Swift中提供了閉包的捕獲列表來對(duì)引用類型進(jìn)行弱引用或者無(wú)主引用的轉(zhuǎn)換:

class MyClassNine {
  var name:String = "HS"
  lazy var closure:()->Void = {
    [unowned self]()->Void in
    print(self.name)
  }
  deinit{
    print("ClassNine deinit")
  }
}
var obj9:MyClassNine? = MyClassNine()
obj9?.closure()
obj9=nil

捕獲列表以中括號(hào)標(biāo)識(shí),多個(gè)捕獲參數(shù)則使用逗號(hào)分隔。

相關(guān)文章

  • SpringBoot3.0集成Redis緩存的實(shí)現(xiàn)示例

    SpringBoot3.0集成Redis緩存的實(shí)現(xiàn)示例

    緩存就是一個(gè)存儲(chǔ)器,常用 Redis作為緩存數(shù)據(jù)庫(kù),本文主要介紹了SpringBoot3.0集成Redis緩存的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03
  • switch循環(huán)所支持的數(shù)據(jù)類型案例分析

    switch循環(huán)所支持的數(shù)據(jù)類型案例分析

    這篇文章主要介紹了switch循環(huán)所支持的數(shù)據(jù)類型,本文通過實(shí)際案例講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06
  • Swift?列舉內(nèi)存管理與異常處理具體代碼

    Swift?列舉內(nèi)存管理與異常處理具體代碼

    內(nèi)存管理和異常處理在任何編程語(yǔ)言中都是核心概念。盡管有很多教程解釋了Swift自動(dòng)引用計(jì)數(shù)的基本原理,但我發(fā)現(xiàn)沒有一個(gè)可以從編譯器的角度對(duì)其進(jìn)行解釋。在本文中,我們將通過詳細(xì)代碼列舉學(xué)習(xí)Swift內(nèi)存管理與異常處理
    2021-11-11
  • Switch語(yǔ)句的技巧

    Switch語(yǔ)句的技巧

    switch語(yǔ)句對(duì)一個(gè)表達(dá)式求值,將結(jié)果與 case 子語(yǔ)句比較,如果匹配,則從 case 處的語(yǔ)句向下執(zhí)行,本文給大家介紹Switch語(yǔ)句的技巧,需要的朋友參考下吧
    2016-02-02
  • Swift?enum枚舉類型使用詳解

    Swift?enum枚舉類型使用詳解

    這篇文章主要為大家介紹了Swift?enum枚舉類型的使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • 使用?Swift?Package?插件生成代碼的示例詳解

    使用?Swift?Package?插件生成代碼的示例詳解

    這篇文章主要介紹了使用?Swift?Package?插件生成代碼,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08
  • 利用Swift實(shí)現(xiàn)一個(gè)響應(yīng)式編程庫(kù)

    利用Swift實(shí)現(xiàn)一個(gè)響應(yīng)式編程庫(kù)

    最近在學(xué)習(xí)swift,最近有空所以總結(jié)一下最近學(xué)習(xí)的內(nèi)容,下面這篇文章主要給大家介紹了關(guān)于利用Swift實(shí)現(xiàn)一個(gè)響應(yīng)式編程庫(kù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-12-12
  • Swift中的條件判斷、循環(huán)、跳轉(zhuǎn)語(yǔ)句基礎(chǔ)學(xué)習(xí)筆記

    Swift中的條件判斷、循環(huán)、跳轉(zhuǎn)語(yǔ)句基礎(chǔ)學(xué)習(xí)筆記

    if、for和while循環(huán)、switch等這些基本的程序流程控制語(yǔ)句基本上是每個(gè)編程語(yǔ)言的標(biāo)配,在入門環(huán)節(jié)中,這里對(duì)Swift中的條件判斷、循環(huán)、跳轉(zhuǎn)語(yǔ)句基礎(chǔ)學(xué)習(xí)筆記作了一個(gè)整理:
    2016-06-06
  • swift4 使用DrawerController實(shí)現(xiàn)側(cè)滑菜單功能的示例代碼

    swift4 使用DrawerController實(shí)現(xiàn)側(cè)滑菜單功能的示例代碼

    這篇文章主要介紹了swift4 使用DrawerController實(shí)現(xiàn)側(cè)滑功能的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-06-06
  • swift中可選值?和!使用的方法示例

    swift中可選值?和!使用的方法示例

    這篇文章主要給大家介紹了關(guān)于swift中可選值?和!使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-11-11

最新評(píng)論