如何解决转义闭包捕获 Swift 中的“inout”参数?

Posted

技术标签:

【中文标题】如何解决转义闭包捕获 Swift 中的“inout”参数?【英文标题】:How can I solve Escaping closure captures 'inout' parameter in Swift? 【发布时间】:2021-07-15 10:58:10 【问题描述】:

我想用一个函数更新一个 State 值,在这个函数中我想使用一个 DispatchQueue 但我收到了这个错误:

Escaping closure captures 'inout' parameter 'currentValue'

我该如何解决这个问题?

struct ContentView: View 
    
    @State private var offset: CGFloat = CGFloat()
    
    var body: some View 
        
        Color.yellow
            .overlay(
                
                Circle()
                    .fill(Color.red)
                    .frame(width: 100.0, height: 100.0, alignment: .center)
                    .offset(y: offset)
                
            )
            .overlay(
                
                Button("update") 
                    
                    updater(currentValue: &offset, goalValue: 300.0)
                    
                
                .font(Font.body.bold())
                .padding()
                
                , alignment: .bottom)
        
    
    


func updater(currentValue: inout CGFloat, goalValue: CGFloat) 
    
    if (currentValue + 1.0) <= goalValue 
        
        currentValue += 1.0
        
        DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.milliseconds(1000)) 

            updater(currentValue: &currentValue, goalValue: goalValue)

        
        
    
    

【问题讨论】:

【参考方案1】:

您可以通过创建一个额外的 var 来修复您的错误。像这样

func updater(currentValue: inout CGFloat, goalValue: CGFloat) 
        var currentValue = currentValue // <--- Here
        if (currentValue + 1.0) <= goalValue 
            
            currentValue += 1.0
            
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.milliseconds(1000)) 
                updater(currentValue: &currentValue, goalValue: goalValue)
            
        
    

但是这样做您的视图将无法更新。你可以通过这个修改你的代码

struct ContentView: View 
    
    @State private var offset: CGFloat = CGFloat()
    
    var body: some View 
        
        Color.yellow
            .overlay(
                
                Circle()
                    .fill(Color.red)
                    .frame(width: 100.0, height: 100.0, alignment: .center)
                    .offset(y: offset)
                
            )
            .overlay(
                
                Button("update") 
                    
                    updater(goalValue: 300.0)
                    
                
                .font(Font.body.bold())
                .padding()
                
                , alignment: .bottom)
        
    
    
    func updater(goalValue: CGFloat) 
        if (offset + 1.0) <= goalValue 
            
            offset += 1.0
            
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + DispatchTimeInterval.milliseconds(1000)) 
                updater(goalValue: goalValue)
            
        
    

【讨论】:

以上是关于如何解决转义闭包捕获 Swift 中的“inout”参数?的主要内容,如果未能解决你的问题,请参考以下文章

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

Swift 4:转义闭包只能通过值显式捕获 inout 参数

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

Alamofire 4、Swift 3:无法返回 StatusCode

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

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