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

Posted

技术标签:

【中文标题】错误:转义闭包捕获变异的“自我”参数【英文标题】:Error: Escaping closure captures mutating 'self' parameter 【发布时间】:2021-03-25 12:57:40 【问题描述】:

我已经在 SO 上查看了有关此主题的其他问题(有很多),但没有一个解决与 @State 相关的此错误。我认为这正是@State 解决的问题!

这里是相关代码

 struct ViewA: View 
    @State private var startAnimation = false
    
    let width: CGFloat
    let height: CGFloat
    
    init(width: CGFloat, height: CGFloat) 
        self.width = width
        self.height = height
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) 
            
            startAnimation = true //<--- The error is on this line
        
            
        
    
    
    var body: some View 
        Circle()
            .frame(width: width, height: height)
            .scaleEffect(CGSize(width: startAnimation ? 5.0 : 1.0 , height: startAnimation ? 5.0 : 1.0))
    

有错误是Escaping closure captures mutating 'self' parameter

现在查看与此错误相关的其他 SO 问题让我知道此错误与 时间延迟更改有关 ...

【问题讨论】:

为什么不使用 .onAppear() ? .onAppear() DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) self.startAnimation = true 好吧...现在为什么它在 .onAppear() 而不是 init() 内部工作?? init 用于初始化变量,而不是在某些时间段内更改变量值。 正确,是用来初始化结构体的。每次需要重绘屏幕时,都会丢弃当前的 ViewA 并创建一个新结构,然后调用 init 来初始化自身。 OnAppear 应该会被调用一次。还有一种更 SwiftUI 的方式来延迟动画可能是:withAnimation(Animation.linear(duration: 0.5).delay(1)) startAnimation = true 【参考方案1】:

我认为这与 @State 属性无关,但与您使用的是 @escaping 闭包这一事实有关。如果在闭包中使用 self ,转义闭包会导致强引用循环。请参阅 link 中解释 @escaping 闭包的精彩文章。

亲切的问候, Mac用户T

【讨论】:

结构体没有引用循环这种东西 好吧,John,你确定 Timer 和 DispatchQueue 也是结构体吗?它们是 Objective-C 的残余。 Timer 和 DispatchQueue 不是结构体。问题中的ViewA: View 是一个结构体。

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

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

获取 JSON,附加到数组:转义闭包捕获变异的“自我”参数

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

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

Swift 3.0 错误:转义闭包只能按值显式捕获 inout 参数

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