日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Swift解决【闭包引起的循环强引用】

發(fā)布時間:2025/3/17 编程问答 11 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Swift解决【闭包引起的循环强引用】 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

循環(huán)強(qiáng)引用還會發(fā)生在當(dāng)你將一個閉包賦值給類實例的某個屬性,并且這個閉包體中又使用了這個類實例時。這個閉包體中可能訪問了實例的某個屬性,例如self.someProperty,或者閉包中調(diào)用了實例的某個方法,例如self.someMethod()。這兩種情況都導(dǎo)致了閉包“捕獲”self,從而產(chǎn)生了循環(huán)強(qiáng)引用。

解決閉包引起的循環(huán)強(qiáng)引用

在定義閉包時同時定義捕獲列表作為閉包的一部分,通過這種方式可以解決閉包和類實例之間的循環(huán)強(qiáng)引用。捕獲列表定義了閉包體內(nèi)捕獲一個或者多個引用類型的規(guī)則。跟解決兩個類實例間的循環(huán)強(qiáng)引用一樣,聲明每個捕獲的引用為弱引用或無主引用,而不是強(qiáng)引用。應(yīng)當(dāng)根據(jù)代碼關(guān)系來決定使用弱引用還是無主引用。

注意 Swift 有如下要求:只要在閉包內(nèi)使用self的成員,就要用self.someProperty或者self.someMethod()(而不只是someProperty或someMethod())。這提醒你可能會一不小心就捕獲了self。

定義捕獲列表

捕獲列表中的每一項都由一對元素組成,一個元素是weak或unowned關(guān)鍵字,另一個元素是類實例的引用(例如self)或初始化過的變量(如delegate = self.delegate!)。這些項在方括號中用逗號分開。

如果閉包有參數(shù)列表和返回類型,把捕獲列表放在它們前面:

lazy var someClosure: (Int, String) -> String = {[unowned self, weak delegate = self.delegate!] (index: Int, stringToProcess: String) -> String in// 這里是閉包的函數(shù)體 } 復(fù)制代碼

如果閉包沒有指明參數(shù)列表或者返回類型,即它們會通過上下文推斷,那么可以把捕獲列表和關(guān)鍵字in放在閉包最開始的地方:

lazy var someClosure: Void -> String = {[unowned self, weak delegate = self.delegate!] in// 這里是閉包的函數(shù)體 } 復(fù)制代碼
弱引用和無主引用

在閉包和捕獲的實例總是互相引用并且總是同時銷毀時,將閉包內(nèi)的捕獲定義為無主引用。

相反的,在被捕獲的引用可能會變?yōu)閚il時,將閉包內(nèi)的捕獲定義為弱引用。弱引用總是可選類型,并且當(dāng)引用的實例被銷毀后,弱引用的值會自動置為nil。這使我們可以在閉包體內(nèi)檢查它們是否存在。

注意 如果被捕獲的引用絕對不會變?yōu)閚il,應(yīng)該用無主引用,而不是弱引用。

案例

class HTMLElement {let name: Stringlet text: String?lazy var asHTML: Void -> String = {[unowned self] inif let text = self.text {return "<\(self.name)>\(text)</\(self.name)>"} else {return "<\(self.name) />"}}init(name: String, text: String? = nil) {self.name = nameself.text = text}deinit {print("\(name) is being deinitialized")}} 復(fù)制代碼

捕獲列表是[unowned self],表示“將self捕獲為無主引用而不是強(qiáng)引用”。

創(chuàng)建并打印HTMLElement實例:

var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world") print(paragraph!.asHTML()) // 打印 “<p>hello, world</p>” 復(fù)制代碼

使用捕獲列表后引用關(guān)系如下圖所示:

這一次,閉包以無主引用的形式捕獲self,并不會持有HTMLElement實例的強(qiáng)引用。如果將paragraph賦值為nil,HTMLElement實例將會被銷毀,并能看到它的析構(gòu)函數(shù)打印出的消息:

paragraph = nil // 打印 “p is being deinitialized” 復(fù)制代碼

引自:http://www.piggybear.net/?p=690

轉(zhuǎn)載于:https://juejin.im/post/5a312c936fb9a0450f21f062

總結(jié)

以上是生活随笔為你收集整理的Swift解决【闭包引起的循环强引用】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。