Captured previous value in onChange is equal to the new value not the old value

When I try to replicate the example from SwiftUI documentation on onChange modifier and capture the previous value, inside the closure the previous value is equal to the new value, not the old one.

Code Block swift
struct ContentView: View {
  @State private var isSubscribed = false
  var body: some View {
    Toggle("Subscribe", isOn: $isSubscribed)
       
    .onChange(of: isSubscribed) { [isSubscribed] newState in
      print(isSubscribed)
      print(newState)
    }
  }
}

In the documentation example, the onChange modifier is attached to the body property, not to a view inside it. Is this how it should be used? Attaching it to the body property in Xcode 12.0 beta (12A6159) doesn't compile.
Post not yet marked as solved Up vote post of natpan Down vote post of natpan
6.8k views
Add a Comment

Replies

I am having the same issue, onChange is not capturing the previous value.

Note, I am able to attach .onChange to the body view and have it compile.
I submitted feedback FB7824176

A good alternative to get old values is to use 'willSet'

@State private var isSubscribed = false {
    willSet {
       print("oldValue: \(isSubscribed)")
    }
  }

In my case I was missing the part in square brackets which captures the old value.

Wrong

.onChange(of: isSubscribed) { newState in      
  print("debug", isSubscribed, newState) // will print the same value twice      
}

Correct

.onChange(of: isSubscribed) { [isSubscribed] newState in      
  print("debug", isSubscribed, newState) // will print two values - old, then new
}

That's an old thread, but this doesn't compile:

.onChange(of: isSubscribed) { [isSubscribed] newState in      
  print("debug", isSubscribed, newState) // will print two values - old, then new
}

I needed to write:

.onChange(of: isSubscribed) { [oldValue = isSubscribed] newState in      
  print("debug", oldValue, newState) // will print two values - old, then new
}