弱引用和無主引用之間有什麼區別?
瞭解 iOS 記憶體管理對於 iOS 和 macOS 開發至關重要。弱自身和無主自身的概念難以理解,尤其對於初學者而言。ARC(自動引用計數)可能為我們解決了許多問題。在不使用值型別時,Swift 仍然要求您在很多時候管理引用。
ARC 或自動引用計數
自動引用計數 (ARC) 用於跟蹤和管理應用程式的記憶體使用情況。在大多數情況下,這意味著記憶體管理在 Swift 中“正常工作”,您無需自己考慮記憶體管理。ARC 會在不再需要類例項時自動釋放類例項使用的記憶體。
請注意,在 Swift 中,預設情況下,引用被計為強引用。
import UIKit
class ProductListController: UIViewController {
// Create a strong reference to a ProductListDataSource() instance. When the ProductListController instance is deallocated, it will decrease the reference count of the ProductListDataSource instance by 1.
let dataSource = ProductListDataSource()
override func viewDidLoad() {
super.viewDidLoad()
}
}
在上面的示例中,ProductListController 類對 ProductListDataSource() 型別具有強引用。
當強引用分配給物件時,物件的引用計數增加 1。當強引用從物件中移除時,物件的引用計數減少 1。
擁有強引用意味著什麼?
讓我們首先了解什麼是強引用。它本質上是一個預設引用(包括指標),但它本身具有特殊性,因為它透過將被引用物件的保留計數增加 1 來保護該物件不被 ARC 釋放。從本質上講,只要任何東西對一個物件具有強引用,它就不會被釋放。這是以後在解釋保留週期等內容時需要記住的一點。
Swift 程式碼庫幾乎完全使用強引用。所有屬性宣告預設都是強引用。通常,當物件層次結構關係是線性的時,可以使用強引用。當它們的層次結構從父級到子級執行時,通常明智地依賴強引用。
UIView.animate(withDuration: 0.5) {
self.view.alpha = 0.5
}
由於 animateWithDuration 是 UIView 上的靜態方法,因此此處的閉包是父級,self 是子級。
弱引用
弱引用是解決 Swift 中保留週期問題的方法之一。請注意,弱引用不會增加或減少物件的引用計數。即使 ARC 的引用計數大於 1,它們也可能被釋放。
基本上,我們在 Swift 中使用 weak 關鍵字將引用標記為弱引用。此外,弱引用不能用 let 關鍵字宣告,因為它最終會被傳遞給 nil。這是因為在弱引用指向它時,物件可能會被釋放。在您認為可能會生成保留週期的程式碼中,應該有一個弱引用。
如何使用弱引用修復保留週期
我們將看到一個如何修復保留週期的示例。我們將建立一個數據源模型類,使用網路請求獲取初始資料。
import UIKit
class ProductListDataSource {
func loadInitialData(_ completion: ((_ isSuccess: Bool) -> ())?) {
// assume perform networking request to fetch initial data
// returning completion handler after finishing the task
completion?(true)
}
}
class ProductListController: UIViewController {
// Created a strong reference to a ProductListDataSource() instance. When the ProductListController instance is deallocated, it will decrease the reference count of the ProductListDataSource instance by 1.
let dataSource = ProductListDataSource()
override func viewDidLoad() {
super.viewDidLoad()
/*
1. Calling the loadInitialData function no longer creates a retain cycle.
2. Self (ProductListController) has a strong reference to the data source.
3. Completion handler has a weak reference to self (ProductListController).
*/
dataSource.loadInitialData { [weak self] isSuccess in
guard let self = self else { return }
// perform tasks that need to be done after successfully fetching data
}
}
}
在上面的示例中,您可以看到我們使用了 self (ProductListController()) 的弱引用,因為它可能需要在從伺服器獲取資料後執行某些操作。
Swift 中的無主引用
無主引用與弱引用非常相似,但有一點區別。無主引用將向您保證在訪問變數時它不會為 nil。
與弱引用類似,無主引用不會增加或減少物件的引用計數。可以說它是修復保留週期的另一種解決方案。當引用指向的例項為 nil 時訪問無主引用會導致程式致命錯誤。
它們之間有什麼區別?
弱引用是指不會阻止 Swift 執行時釋放被引用物件的引用。
另一方面,無主引用是指不會對被引用物件保持強引用的引用。但是,與弱引用不同,無主引用被假定始終具有值。
總結兩者的區別 −
弱引用和無主引用的區別
| 弱引用 | 無主引用 |
|---|---|
| 它可以宣告為可選的。 | 它不能宣告為可選的。 |
| 它可以隨時變為 nil。 | 它不能隨時變為 nil。 |
| 它可以防止物件被釋放。 | 它不會防止物件被釋放。 |
| 如果訪問已釋放的引用物件,則發生執行時錯誤的可能性較小。 | 如果訪問已釋放的引用物件,則發生執行時錯誤的可能性很高。 |
哪個引用適合使用?
使用弱引用
當兩個物件之間存在一種關係,其中一個物件不應對另一個物件有強烈的控制時,您應該使用弱引用來停止保留迴圈。當兩個物件相互之間存在強引用時,就會產生保留迴圈,從而阻止 Swift 執行時釋放任何一個物件。
例如,在兩個物件之間建立父子關係時,通常會對孩子的對父級的引用使用弱引用,以避免孩子永久保留父級。
使用無主引用
當兩個物件之間存在一種關係,其中一個物件不對另一個物件有強烈的控制,但您確信被引用物件將在引用物件的整個生命週期內始終存在時,您應該使用無主引用。
例如,如果檢視控制器始終呈現相同的檢視,則您可以對檢視控制器對檢視的引用使用無主引用,因為只要檢視控制器存在,檢視就會始終存在。
結論
總之,兩種引用在各自的場景中都扮演著重要的角色。但在大多數情況下,我們在應用程式中使用弱引用。這是因為弱引用在記憶體管理方面更好。由於弱引用可以宣告為可選的並處理 nil,因此建議使用它們。
資料結構
網路
關係資料庫管理系統
作業系統
Java
iOS
HTML
CSS
Android
Python
C 程式設計
C++
C#
MongoDB
MySQL
Javascript
PHP