SwiftUI 转义闭包捕获变异的“自我”参数

Posted

技术标签:

【中文标题】SwiftUI 转义闭包捕获变异的“自我”参数【英文标题】:SwiftUI Escaping closure captures mutating 'self' parameter 【发布时间】:2020-03-15 23:43:01 【问题描述】:

我有一个可以通过两种方式打开的视图。一个带有提供给它的数据,另一个带有对 Firestore 文档的文档引用。我创建了两个构造函数,第一个提供数据,另一个提供文档参考。 然后我使用此引用进行网络调用位我收到错误:

Escaping closure captures mutating 'self' parameter

关于如何解决这个问题的任何想法?

@State var request: RequestModel?

init(request: RequestModel) 
    self.request = request


init(reference: DocumentReference) 
    FirestoreService().fetchDocument(documentReference: reference)  (request: RequestModel) in
        self.request = request
    

【问题讨论】:

视图是结构体。尝试在闭包中更改它们是没有意义的。你能做的最好的就是改变一个副本。 你能说得具体一点吗? 【参考方案1】:

很抱歉,上面的答案是错误的。

对象的初始化器不能做任何异步操作。它的工作是立即生成对象,并初始化其所有属性

--> 这是绝对错误的。

10 年来,我在 Objective-C/C/Swift 中成功完成了大量多线程编程:没有任何内存泄漏、数据访问或访问竞争。

我已经成功地让一些对象在制作我的游戏时异步初始化,尤其是。当我需要以高性能方式创建尽可能多的对象以及许多惰性对象时。

initializers 可以做异步,但是这里的问题是 'self' 在下面的转义闭包中不能被修改。

init(reference: DocumentReference) 
    FirestoreService().fetchDocument(documentReference: reference)     
        (request: RequestModel) in
         self.request = request

详细的初始化器中的闭包是

        
    @escaping [unowned self] (request: RequestModel) in

        self.request = request

因此,闭包中的“self”将比函数更长寿。 而上面的代码似乎是 View 类型的一部分,被创建为结构体。

来自https://docs.swift.org/swift-book/LanguageGuide/Closures.html

“如果 self 是结构或枚举的实例,则始终可以隐式引用 self。但是,当 self 是结构或枚举的实例时,转义闭包无法捕获对 self 的可变引用。结构和枚举不允许共享可变性,如结构和枚举是值类型中所述。"

因此,'self' 不能是可变的。

这就是您的代码收到错误消息的原因:“Escaping Closure captures mutating 'self' parameter”。

更好的解决方案是将部件移动到修饰符内的另一个位置,例如“didAppear()”。

因为提问者没有在此处提供更多他或她的代码。 我无法在这里提供更具体的答案。

【讨论】:

【参考方案2】:

对象的初始化器不能做任何异步操作。它的工作是立即生成对象,并初始化其所有属性。

【讨论】:

那么我怎样才能达到预期的效果呢?我试图将逻辑移动到一个函数并在初始化时调用它。它的工作,但视图没有被更新。 如果你有一些数据需要通过网络获取,那是某种 ObservableObject 类实例存在于数据空间中,而不是在实例化时初始化的实例属性。 这已经讨论过很多次了。为什么不搜索?这是一个开始:***.com/questions/tagged/swiftui+firebase 好的,我会检查它...最后一个问题..为什么这些调用在 .appear() 中工作正常? 因为出现的不是对象初始化。【参考方案3】:

这大概可以分为两个不同的问题:

1: 结构的属性不能在像'didSet'或'willSet'这样的闭包中改变。

2:只有使用@ObservedObject 或@EnvironmentObject .etc 声明的Observable struct 才能在属性更改时调用UI 进行更新。因为这样的修饰符赋予属性特殊的 getter 和 setter 函数

【讨论】:

以上是关于SwiftUI 转义闭包捕获变异的“自我”参数的主要内容,如果未能解决你的问题,请参考以下文章

转义闭包捕获变异的“自我”参数,Firebase

错误:转义闭包捕获变异的“自我”参数

转义闭包捕获 Swift 中的变异“self”参数错误

在 Swift 3.0 中的转义闭包中改变自我(结构/枚举)

转义闭包捕获非转义参数“函数” Xcode 说

Swift 5:转义闭包捕获'inout'参数