skip to Main Content

I’m trying to detect a change on my @State variables to update some text but I cannot get it to work because the .onChange modifier is throwing this error:

Cannot convert value of type ‘Double’ to expected argument type ‘()’

struct CalcView: View {
    @State private var width = 0.0

    var body: some View {
        VStack {
            Button(action: {
                width += 1.0
            }, label: {
                Text("Increment width")
            })
        }
        .onChange(of: width) { // This line specifically 
            print("Width Changed")
        }
    }
}

2

Answers


  1. The closure you’re calling with the onChange modifier doesn’t take any arguments, but onChange wants to pass a Double to that closure. Try changing .onChange(of: width) { to this:

    .onChange(of: width) { newWidth in

    Login or Signup to reply.
  2. To never get stuck in this again
    start type method name, then wait for the completion

    .onChange

    the completion will popup with the details of the method
    with the arguments

    now you can see that .onChange() wants a value that conforms to the Equatable protocol see more about Equatable

    because "width" value type is Double type so it conforms to Equatable

    .onChange(of: Equatable, perform: (Equatable) -> Void)
    

    you can press enter to pass a closure in perform

     .onChange(of: width, perform: { newValue in   })
    

    if you do not want to use newValue change it to _

    .onChange(of: width, perform: { _ in   })
    

    or you can even pass a function that has (Equatable) -> Void type

      .onChange(of: width, perform: performOnChangeAction)
    
    
    func performOnChangeAction<T: Equatable>(newValue: T){
        print(newValue)
    }
    

    T is a generic type that conforms to Equatable learn more about generics

    Note that you cannot change newValue
    newValue

    you can always access and change width value with your conditions

      .onChange(of: width, perform: { newValue in
                            if newValue >= 10.0{return}
                            if newValue >= 20.0 {
                                widthError = true
                                width = 0.0
                            }
                        })
    

    but that leads to more complex code in the view and the possibility of entering an infinite loop because every time you change width it will trigger .onChange()

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search