最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Swift中如何避免循環(huán)引用的方法

 更新時(shí)間:2017年12月13日 08:36:37   作者:愛抽煙的芭比  
本篇文章主要介紹了Swift中如何避免循環(huán)引用的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

內(nèi)存管理中經(jīng)常會(huì)遇到的一個(gè)問題便是循環(huán)引用。首先,我們來了解一下iOS是如何進(jìn)行內(nèi)存管理的。

和OC一樣,swift也是使用自動(dòng)引用計(jì)數(shù)ARC(Auto Reference Counteting)來自動(dòng)管理內(nèi)存的,所以我們不需要過多考慮內(nèi)存管理.當(dāng)某個(gè)類實(shí)例不需要用到的時(shí)候,ARC會(huì)自動(dòng)釋放其占用的內(nèi)存.

ARC

ARC(Automatic Reference Counting) 是蘋果的自動(dòng)內(nèi)存管理機(jī)制。正如其名:自動(dòng)引用計(jì)數(shù),根據(jù)引用計(jì)數(shù)來決定內(nèi)存塊是否應(yīng)該被釋放。

當(dāng)一個(gè)對(duì)象被創(chuàng)建的時(shí)候,它的引用計(jì)數(shù)為1。在它的生命周期內(nèi),其引用計(jì)數(shù)可以增加或減少。當(dāng)它的引用計(jì)數(shù)減為0的時(shí)候,其所占用內(nèi)存便會(huì)被釋放。其生命周期如圖所示:


強(qiáng)引用和弱引用(Strong/Weak References)

定義一個(gè)變量的時(shí)候可以聲明其strong和weak屬性,默認(rèn)是strong類型。

struct Example {
 var strongView = UIView()
 weak var weakView = UIView()
}

強(qiáng)引用和弱引用有什么不同呢?

強(qiáng)引用會(huì)使變量的引用計(jì)數(shù)加1。如果一個(gè)對(duì)象的引用計(jì)數(shù)為2,當(dāng)它再次被強(qiáng)引用的時(shí)候,它的引用計(jì)數(shù)會(huì)變?yōu)?。

弱引用不會(huì)增加引用計(jì)數(shù)。如果一個(gè)對(duì)象的引用計(jì)數(shù)為2,當(dāng)它再次被弱引用的時(shí)候,它的引用計(jì)數(shù)仍為2。

強(qiáng)引用的對(duì)象能保證其被調(diào)用的時(shí)候仍在內(nèi)存中,而弱引用不行。

循環(huán)引用和內(nèi)存泄漏

當(dāng)A引用B中的成員變量,而B又對(duì)A中的成員變量有引用的時(shí)候就會(huì)發(fā)生循環(huán)引用。
比如:

class Book {
 private var pages = [Page]()
 
 func add(_ page : Page) {
  pages.append(page)
 }
}

class Page {
 private var book : Book

 required init(book : Book) {
  self.book = book
 }
}

let book = Book()
let page = Page(book: book)
book.add(page)

此時(shí),book對(duì)page有強(qiáng)引用,同時(shí)page對(duì)book也有強(qiáng)引用。這個(gè)時(shí)候便有循環(huán)引用,會(huì)導(dǎo)致內(nèi)存泄漏。

對(duì)于這種兩個(gè)變量的相互強(qiáng)引用導(dǎo)致的內(nèi)存泄漏該如何解決呢?

Structs 和 Classes

正確的使用struct 和 class能避免循環(huán)引用的發(fā)生。

struct 和 class 都有成員變量,函數(shù)和協(xié)議。那么,它們之間有什么區(qū)別呢?

struct 是 值類型。
class 是 引用類型。

當(dāng)引用或者傳遞 值類型 變量的時(shí)候,它會(huì)在內(nèi)存中重新分配地址,copy內(nèi)容到新的地址中。

struct Element {
 var name : String
 var number : Int
}

var firstElement = Element(name: "A", number: 1)

var secondElement = firstElement
secondElement.name = "B"
secondElement.number = 2

print(firstElement)
print(secondElement)

輸出的結(jié)果為:

Element(name: “A”, number: 1)
Element(name: “B”, number: 2)

當(dāng)引用或者傳遞 引用類型 變量的時(shí)候,新的變量指針指向的仍是原先的內(nèi)存地址。此時(shí)原先的變量值改變的話,也會(huì)導(dǎo)致新變量值的變化。

比如:

class Element {
 var name : String
 var number : Int
 
 required init(name : String, number : Int) {
  self.name = name
  self.number = number
 }
}

extension Element : CustomStringConvertible {
 var description : String {
  return "Element(name: \(name), number: \(number))"
 }
}

var firstElement = Element(name: "A", number: 1)

var secondElement = firstElement
secondElement.name = "B"
secondElement.number = 2

print(firstElement)
print(secondElement)

此時(shí)的輸出結(jié)果為:

Element(name: B, number: 2)
Element(name: B, number: 2)

我們?yōu)槭裁丛诖擞懻撝殿愋秃鸵妙愋湍兀?/p>

回到之前book和pages的例子。我們用struct代替class:

struct Book {
 private var pages = [Page]()
 
 mutating func add(_ page : Page) {
  pages.append(page)
 }
}

struct Page {
 private var book : Book
 
 init(book : Book) {
  self.book = book
 }
}

var book = Book()
let page = Page(book: book)
book.add(page)

此時(shí),便不會(huì)發(fā)生循環(huán)引用的情況。

如果仍想使用class的話,可以使用weak來避免循環(huán)引用:

class Book {
 private var pages = [Page]()
 
 func add(_ page : Page) {
  pages.append(page)
 }
}

class Page {
 private weak var book : Book?
 
 required init(book : Book) {
  self.book = book
 }
}

let book = Book()
let page = Page(book: book)
book.add(page)

Protocols

Protocols在swift中使用的很廣泛。class,struct 和 enum 都可以使用Protocol。但是如果使用不當(dāng)?shù)脑?,同樣?huì)引起循環(huán)引用。

比如:

protocol ListViewControllerDelegate {
 func configure(with list : [Any])
}

class ListViewController : UIViewController {
 
 var delegate : ListViewControllerDelegate?
 
 override func viewDidLoad() {
  super.viewDidLoad()
 }
 
}

ListViewController 中的delegate變量是strong類型的,可以引用任何實(shí)現(xiàn)它protocol的變量。假如實(shí)現(xiàn)其protocol的變量對(duì)該 view controller 同樣有強(qiáng)引用的話會(huì)怎么樣? 聲明delegate為weak可能會(huì)避免這種情況,但是這樣的話會(huì)引起編譯錯(cuò)誤,因?yàn)閟tructs和enums不能引用weak變量。

該如何解決呢?當(dāng)聲明protocol的時(shí)候,我們可以指定只有class類型的變量可以代理它,這樣的話就可以使用weak來修飾了。

protocol ListViewControllerDelegate : class {
 func configure(with list : [Any])
}

class ListViewController : UIViewController {
 
 weak var delegate : ListViewControllerDelegate?
 
 override func viewDidLoad() {
  super.viewDidLoad()
 }
 
}

Closures

Closures 導(dǎo)致循環(huán)引用的原因是:Closures對(duì)使用它們的對(duì)象有一個(gè)強(qiáng)引用。

比如:

class Example {

 private var counter = 0
 
 private var closure : (() -> ()) = { }
 
 init() {
  closure = {
   self.counter += 1
   print(self.counter)
  }
 }
 
 func foo() {
  closure()
 }
 
}

此時(shí),對(duì)象對(duì)closure有一個(gè)強(qiáng)引用,同時(shí)在closure的代碼塊中又對(duì)該對(duì)象本身有一個(gè)強(qiáng)引用。這樣就引起了循環(huán)引用的發(fā)生。

這種情況,可以有兩種方法來解決這個(gè)問題。

1.使用[unowned self]:

class Example {

 private var counter = 1
 
 private var closure : (() -> ()) = { }
 
 init() {
  closure = { [unowned self] in
   self.counter += 1
   print(self.counter)
  }
 }
 
 func foo() {
  closure()
 }
 
}

使用[unowned self] 的時(shí)候需要注意的一點(diǎn)是:調(diào)用closure的時(shí)候如果對(duì)象已經(jīng)被釋放的話,會(huì)出現(xiàn)crash。

2.使用[weak self]:

class Example {

 private var counter = 1
 
 private var closure : (() -> ()) = { }
 
 init() {
  closure = { [weak self] in
   self?.counter += 1
   print(self?.counter ?? "")
  }
 }
 
 func foo() {
  closure()
 }
 
}

[weak self] 和[unowned self] 的區(qū)別是 [weak self]處理的時(shí)候是一個(gè)可選類型。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • swift 錯(cuò)誤處理do catch try try!使用詳解

    swift 錯(cuò)誤處理do catch try try!使用詳解

    這篇文章主要介紹了swift 錯(cuò)誤處理do catch try try!使用詳解的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • Swift初始化方法的使用介紹

    Swift初始化方法的使用介紹

    Swift有著超級(jí)嚴(yán)格的初始化方法,不僅強(qiáng)化了designated初始化方法的地位,所有不加修飾的init方法都需要在方法中確保非Optional的實(shí)例變量被賦值初始化,下面這篇文章主要給大家介紹了關(guān)于Swift中初始化init的相關(guān)資料,需要的朋友可以參考下。
    2022-08-08
  • Swift?并發(fā)修改Sendable?閉包實(shí)例詳解

    Swift?并發(fā)修改Sendable?閉包實(shí)例詳解

    這篇文章主要為大家介紹了Swift?并發(fā)修改Sendable?閉包實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • RxSwift發(fā)送及訂閱 Subjects、Variables代碼示例

    RxSwift發(fā)送及訂閱 Subjects、Variables代碼示例

    這篇文章主要介紹了RxSwift發(fā)送及訂閱 Subjects、Variables代碼示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Swift類型創(chuàng)建之自定義一個(gè)類型詳解

    Swift類型創(chuàng)建之自定義一個(gè)類型詳解

    這篇文章主要介紹了Swift類型創(chuàng)建之自定義一個(gè)類型詳解,本文講解了自定義原型、實(shí)現(xiàn)默認(rèn)值、支持基本布爾型初始化、支持Bool類型判斷、支持兼容各們各派的類型、完善OCBool的布爾基因體系等內(nèi)容,需要的朋友可以參考下
    2015-05-05
  • SwiftUI開發(fā)總結(jié)combine原理簡(jiǎn)單示例詳解

    SwiftUI開發(fā)總結(jié)combine原理簡(jiǎn)單示例詳解

    這篇文章主要為大家介紹了SwiftUI開發(fā)總結(jié)combine原理簡(jiǎn)單示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • 初步理解Swift中的泛型

    初步理解Swift中的泛型

    這篇文章主要介紹了初步理解Swift中的泛型,是Swift入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-07-07
  • swift 3.0 實(shí)現(xiàn)短信驗(yàn)證碼倒計(jì)時(shí)功能

    swift 3.0 實(shí)現(xiàn)短信驗(yàn)證碼倒計(jì)時(shí)功能

    這篇文章主要介紹了swift 3.0 實(shí)現(xiàn)短信驗(yàn)證碼倒計(jì)時(shí)功能的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • 淺談swift 4.0中private所發(fā)生的變化

    淺談swift 4.0中private所發(fā)生的變化

    Swift 4是蘋果計(jì)劃于2017年秋季推出的最新版本,其主要重點(diǎn)是提供與Swift 3代碼的源兼容性,并努力實(shí)現(xiàn)ABI穩(wěn)定性。下面這篇文章主要給大家介紹了關(guān)于swift 4.0中private所發(fā)生的一些變化,需要的朋友可以參考下。
    2017-12-12
  • Swift5中fileprivate與private的差別淺析

    Swift5中fileprivate與private的差別淺析

    這篇文章主要給大家介紹了關(guān)于Swift5中fileprivate與private的差別的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Swift5具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09

最新評(píng)論

龙川县| 乐至县| 卢氏县| 盱眙县| 包头市| 宝鸡市| 汪清县| 华池县| 开封市| 麦盖提县| 北碚区| 广宁县| 新闻| 正安县| 道真| 台安县| 潮州市| 曲沃县| 梧州市| 平昌县| 镇原县| 广平县| 漳平市| 南乐县| 隆尧县| 天镇县| 沅陵县| 通山县| 凤翔县| 太白县| 册亨县| 德保县| 丹凤县| 云阳县| 从化市| 蓬莱市| 横峰县| 乌苏市| 阿瓦提县| 南木林县| 平定县|