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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Swift之深入解析Xcode13对Swift对象生命周期的优化

發布時間:2024/5/21 编程问答 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Swift之深入解析Xcode13对Swift对象生命周期的优化 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
  • 在 Xcode13 中,在 Build Setting 中,新增 Optimize Object Lifetimes 編譯選項,默認是關閉的,Apple 建議將該選項設置為 YES,打開此優化項,可以減小 Swift 對象的生命周期,這樣就可以更高效的使用內存。

  • 在修改編譯器設置為 YES 之前,先了解下 Swift 中的 ARC,需要注意以下幾點:
    • 對象的生命周期從 init() 開始到最后一次使用結束;
    • 在生命周期結束之后,ARC 會將對象 dealloc;
    • ARC 通過引用計數來追蹤對象的生命周期;
    • Swift 匯編器通過插入 retain/release 操作,來控制引用計數;
    • 當對象的引用計數為 0 時,Swift runtime 會將對象 dealloc。
  • 現有如下示例代碼:
class Traveler {var name: Stringvar destination: String?init(name:String) {self.name = name} } func test() {let travel1 = Traveler(name: "Kody") // ①// Retainlet travel2 = travel1 // ②// Release // ③travek2.destination = "Big Sur" // ④ // Releaseprint("Done traveling") }
  • 編譯器編譯器會在引用開始時插入 retain 操作,以及在最后一次使用時,插入 release 操作,由此可以分析出:
    • ① Travler 對象初始化時,引用計數為 1;
    • ② 在 travl2 引用 trvel1 時,對 Travler 對象進行 retain 操作,此時,引用計數為 2;
    • ③ 在最后一次使用 travel1 時,對 Travler 對象進行 release 操作,此時引用計數為 1;
    • ④ 在最后一次使用 travel2 時,對 Travler 對象進行 release 操作,此時引用計數為 0。
  • 那么,此時 Travler 對象的生命周期從初始化(①)開始,到最后一次使用(④)結束。
  • 在開啟優化的情況下,運行該函數,結果為:
Traveler deinit ........ Done traveling
  • 可以看出,在執行 print(“Done traveling”) 之前,Traveler 已經被釋放,這樣能夠保證對象的最短生命周期。和 C++ 、OC 是不一樣的,后者是在右括號執行完成后,才會銷毀對象。
  • 在大多數情況下,是沒有問題的,但是如果存在弱引用(weak)或無主引用(unown)就需要特別注意,來看如下示例:
class Traveler {var name: Stringvar account: Account?init(name:String) {self.name = name} }class Account {weak var traveler: Traveler?var points: Intinit(points: Int, traveler: Traveler?) {self.traveler = travelerself.points = points}func printSummary() {if let travel = traveler {print("\(travel.name) has \(points) points")}} }func test() { let travel = Traveler(name: "Kody") let account = Account(points: 1000, traveler: travel)travel.account = accountaccount.printSummary() }
  • Travel 對 Account 對象強引用,Account 對 Travel 對象弱引用。可以注意到,由于 account 引用 travel 是弱引用, 在代碼 travel.account = account 時,此時,travel 對象已經被釋放,當執行 travel.account = account 時,travel 對象為 nil,條件不成立,不會打印分數,此時,將會產生 bug。
  • 通過 withExtendedLifetime 可以延長對象的生命周期,防止潛在的錯誤。如下所示,將 travel 的生命周期延長至 account.printSummary() 執行完:
func test() {let travel = Traveler(name: "Kody")let account = Account(points: 1000, traveler: travel)travel.account = accountwithExtendedLifetime(travel, {account.printSummary()}) }
  • 或者使用 defer,延長至整個函數結束:
func test() {let travel = Traveler(name: "Kody")let account = Account(points: 1000, traveler: travel)defer {withExtendedLifetime(travel, {})}travel.account = accountaccount.printSummary() }
  • 但這種方式不好,這會增加維護成本,也違背減少對象生命周期的初衷。
  • 如果可以把向對象的訪問限制為只允許強引用,就可以防止對象生命周期意外。在這里,printSummary() 函數被移回到了 Traveler 類并且 Account 類中的弱引用是隱藏的,現在必須通過 Travel 調用 printSummary() 函數,由于在 Traveler 中,對 Account 是強引用,可以消除潛在的錯誤。如下所示:
class Traveler {var name: Stringvar account: Account?init(name:String) {self.name = name}func printSummary() {if let account = account {print("\(name) has \( account.points) points")}} }class Account {private weak var traveler: Traveler?var points: Intinit(points: Int, traveler: Traveler?) {self.traveler = travelerself.points = points} } func test() {let travel = Traveler(name: "Kody") let account = Account(points: 1000, traveler: travel)travel.account = accounttravel.printSummary() }
  • 那么,現在重新設計,避免 weak/unown 引用。增加一個中間類,把必須的信息存儲到中間類中,打破原來的弱引用或者 unown 引用,使用中間類打破對象之間的互相引用。重新設計過后,類聲明如下:
class PersonalInfo {var name: String }class T raveler {var info: PersonalInfovar account: Account? }class Account {var info: PersonalInfovar points: Int }
  • 它們之間的引用關系如圖所示:

  • 開啟優化之后,會縮短對象的生命周期,如果在工程在對象的 deinit 方法做了依賴外部對象,那么可能此時依賴的外部對象已經釋放,從而造成一些邏輯錯誤,這里需要注意。

總結

以上是生活随笔為你收集整理的Swift之深入解析Xcode13对Swift对象生命周期的优化的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。