国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Swift - Swift中如何避免循環引用的方法

Swift中如何避免循環引用的方法

2021-01-09 17:42愛抽煙的芭比 Swift

本篇文章主要介紹了Swift中如何避免循環引用的方法,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

內存管理中經常會遇到的一個問題便是循環引用。首先,我們來了解一下iOS是如何進行內存管理的。

和OC一樣,swift也是使用自動引用計數ARC(Auto Reference Counteting)來自動管理內存的,所以我們不需要過多考慮內存管理.當某個類實例不需要用到的時候,ARC會自動釋放其占用的內存.

ARC

ARC(Automatic Reference Counting) 是蘋果的自動內存管理機制。正如其名:自動引用計數,根據引用計數來決定內存塊是否應該被釋放。

當一個對象被創建的時候,它的引用計數為1。在它的生命周期內,其引用計數可以增加或減少。當它的引用計數減為0的時候,其所占用內存便會被釋放。其生命周期如圖所示:

Swift中如何避免循環引用的方法

強引用和弱引用(Strong/Weak References)

定義一個變量的時候可以聲明其strong和weak屬性,默認是strong類型。

?
1
2
3
4
struct Example {
 var strongView = UIView()
 weak var weakView = UIView()
}

強引用和弱引用有什么不同呢?

強引用會使變量的引用計數加1。如果一個對象的引用計數為2,當它再次被強引用的時候,它的引用計數會變為3。

弱引用不會增加引用計數。如果一個對象的引用計數為2,當它再次被弱引用的時候,它的引用計數仍為2。

強引用的對象能保證其被調用的時候仍在內存中,而弱引用不行。

循環引用和內存泄漏

當A引用B中的成員變量,而B又對A中的成員變量有引用的時候就會發生循環引用。
比如:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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)

此時,book對page有強引用,同時page對book也有強引用。這個時候便有循環引用,會導致內存泄漏。

對于這種兩個變量的相互強引用導致的內存泄漏該如何解決呢?

Structs 和 Classes

正確的使用struct 和 class能避免循環引用的發生。

struct 和 class 都有成員變量,函數和協議。那么,它們之間有什么區別呢?

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

當引用或者傳遞 值類型 變量的時候,它會在內存中重新分配地址,copy內容到新的地址中。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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)

輸出的結果為:

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

當引用或者傳遞 引用類型 變量的時候,新的變量指針指向的仍是原先的內存地址。此時原先的變量值改變的話,也會導致新變量值的變化。

比如:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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)

此時的輸出結果為:

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

我們為什么在此討論值類型和引用類型呢?

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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)

此時,便不會發生循環引用的情況。

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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。但是如果使用不當的話,同樣會引起循環引用。

比如:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
protocol ListViewControllerDelegate {
 func configure(with list : [Any])
}
 
class ListViewController : UIViewController {
 
 var delegate : ListViewControllerDelegate?
 
 override func viewDidLoad() {
  super.viewDidLoad()
 }
 
}

ListViewController 中的delegate變量是strong類型的,可以引用任何實現它protocol的變量。假如實現其protocol的變量對該 view controller 同樣有強引用的話會怎么樣? 聲明delegate為weak可能會避免這種情況,但是這樣的話會引起編譯錯誤,因為structs和enums不能引用weak變量。

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
protocol ListViewControllerDelegate : class {
 func configure(with list : [Any])
}
 
class ListViewController : UIViewController {
 
 weak var delegate : ListViewControllerDelegate?
 
 override func viewDidLoad() {
  super.viewDidLoad()
 }
 
}

Closures

Closures 導致循環引用的原因是:Closures對使用它們的對象有一個強引用。

比如:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Example {
 
 private var counter = 0
 
 private var closure : (() -> ()) = { }
 
 init() {
  closure = {
   self.counter += 1
   print(self.counter)
  }
 }
 
 func foo() {
  closure()
 }
 
}

此時,對象對closure有一個強引用,同時在closure的代碼塊中又對該對象本身有一個強引用。這樣就引起了循環引用的發生。

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

1.使用[unowned self]:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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] 的時候需要注意的一點是:調用closure的時候如果對象已經被釋放的話,會出現crash。

2.使用[weak self]:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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] 的區別是 [weak self]處理的時候是一個可選類型。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://www.jianshu.com/p/f9bc8afd5b53

延伸 · 閱讀

精彩推薦
  • SwiftSwift的74個常用內置函數介紹

    Swift的74個常用內置函數介紹

    這篇文章主要介紹了Swift的74個常用內置函數介紹,這篇文章列舉出了所有的Swift庫函數,內置函數是指無需引入任何模塊即可以直接使用的函數,需要的朋友可...

    Swift教程網5802020-12-19
  • Swiftmac git xcrun error active developer path 錯誤

    mac git xcrun error active developer path 錯誤

    本文主要是講訴了如何解決在mac下使用git;xcode4.6的環境時,出現了錯誤(mac git xcrun error active developer path)的解決辦法,希望對大家有所幫助...

    Swift教程網2232020-12-16
  • SwiftSwift教程之基礎數據類型詳解

    Swift教程之基礎數據類型詳解

    這篇文章主要介紹了Swift教程之基礎數據類型詳解,本文詳細講解了Swift中的基本數據類型和基本語法,例如常量和變量、注釋、分號、整數、數值類型轉換等...

    Swift教程網5162020-12-18
  • SwiftSwift使用CollectionView實現廣告欄滑動效果

    Swift使用CollectionView實現廣告欄滑動效果

    這篇文章主要為大家詳細介紹了Swift使用CollectionView實現廣告欄滑動效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    Stevin的技術博客12372021-01-13
  • SwiftSwift實現多個TableView側滑與切換效果

    Swift實現多個TableView側滑與切換效果

    這篇文章主要為大家詳細介紹了Swift實現多個TableView側滑與切換效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    乞力馬扎羅的雪雪5822021-01-08
  • SwiftSwift能代替Objective-C嗎?

    Swift能代替Objective-C嗎?

    這是我在網上上看到的答案,復制粘貼過來和大家分享一下,因為我和很多人一樣很關心Swift的出現對Mac開發的影響和對Objective-C的影響。...

    Swift教程網4412020-12-16
  • SwiftSwift中轉義閉包示例詳解

    Swift中轉義閉包示例詳解

    在Swift 中的閉包類似于結構塊,并可以在任何地方調用,下面這篇文章主要給大家介紹了關于Swift中轉義閉包的相關資料,需要的朋友可以參考下...

    小小小_小朋友11412021-12-26
  • Swiftswift where與匹配模式的實例詳解

    swift where與匹配模式的實例詳解

    這篇文章主要介紹了swift where與匹配模式的實例詳解的相關資料,這里附有簡單的示例代碼,講的比較清楚,需要的朋友可以參考下...

    追到夢的魔術師14382021-01-06
主站蜘蛛池模板: 国产精品一二三区 | 欧美日韩第一区 | 久久国产精品久久 | av看片网| 日韩精品免费一区二区三区 | 希岛爱理在线 | 成人a视频在线观看 | 视频a区| 欧美电影在线观看网站 | 日本不卡免费一区二区三区综合久久 | 毛片久久久 | 久久小视频 | 精品久久久久久久 | 欧美一区久久 | 久久国产亚洲精品 | 亚洲欧美日韩精品久久亚洲区 | av三级在线观看 | 精品国内 | 懂色aⅴ精品一区二区三区蜜月 | 亚洲精品视频在线 | 操操操影院 | 欧美日韩精品久久久 | 天天草天天干 | 国产专区在线 | 成人在线小视频 | 91网页版| 91xxx在线观看 | 亚洲三级在线观看 | av久草| 在线一区观看 | 成人av免费在线播放 | 国产精品久久久久久婷婷天堂 | 日韩精品三区 | 黄色一级视频 | 九一精品| 欧美视频日韩视频 | 日韩成人片 | 久久69精品久久久久久久电影好 | 91精品一区二区 | 中文字幕在线观看一区二区 | 精品国产精品三级精品av网址 |