簡體   English   中英

如何在沒有在 Swift 中使用引用類型的情況下將 @escaping 用於在 didSet 中使用的函數?

[英]How can use @escaping for a func which used in didSet without using a reference type in Swift?

這個向下的代碼工作得很好! 一旦我用'@escaping'更新testFunc,它就會開始出錯

轉義閉包捕獲變異的“自我”參數

struct TestType {

    var string: String {
        didSet(oldValue) {
            if (oldValue != string) {
  
                testFunc(string: string, result: { resultValue in
                    value = resultValue
                })
            }
        }
    }
    
   private(set) var value: String
 
}


func testFunc(string: String, result: (String) -> Void) {
    result(string + " updated!")
}

我的目標是能夠使用:

func testFunc(string: String, result: @escaping (String) -> Void) {
    result(string + " updated!")
}

如何在不使用引用類型的情況下解決問題?

struct中的@escaping閉包中捕獲變異self的問題在於,理論上 Swift 可能會嘗試如何做到這一點實際上只有兩種選擇。

第一個是捕獲對struct的引用,但在許多情況下它存在於堆棧中。 由於可以稍后調用@escaping閉包,這意味着寫入堆棧上self所在的位置,但可能不再存在。 如果在堆棧縮小時發生這種情況,那么您正在寫入一個任何其他代碼實際上都無法訪問的地址。 如果它發生在堆棧重新增長(或更大)時,那么您可能會踩到不相關的數據,可能是某個函數的返回地址。 如果幸運的話,結果將是程序崩潰。 如果你不走運,它會默默地做錯事。

另一種可能的實現是 Swift 可以捕獲一個副本,當然,可以安全地寫入該副本,但任何其他代碼都無法訪問。 這很沒有意義。

Swift 還有第三種選擇,它可以將結構裝箱(實際上就是將它放在堆上)。 問題是沒有其他人會知道堆位置。 同樣,這毫無意義……而且比在堆棧上分配東西要慢得多。

如果你真的需要捕獲一個變異的self ,那么你需要TestType是一個class ,但這意味着你的其余代碼必須在編寫時考慮到引用語義。

很有可能,您需要考慮以不同的方式嘗試解決的任何問題。 如果不知道那是什么,就不可能提出具體的解決方案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM