How can I solve Escaping closure captures 'inout' parameter in Swift?

Viewed 184

I want update a State value with a function, in this function I want use a DispatchQueue but I am getting this error:

Escaping closure captures 'inout' parameter 'currentValue'

How can I solve this issue?

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 Answers

You can fix your error by creating one extra var. Like this

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)
            }
        }
    }

but by doing this your view can't update. You can modify your code by this

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)
            }
        }
    }
}
Related