繁体   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