iOS 16 Compatible onChange with Old Values
Closure capture technique to access previous values in onChange on iOS 16.
iOS 16 Compatible onChange with Old Values
The Problem
iOS 17’s onChange(of:old:new:) provides both previous and current values. iOS 16 only has onChange(of:) with the new value.
Solution: Closure Capture
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import SwiftUI
public extension View {
@ViewBuilder
func onChangeCompat<V>(
for value: V,
_ action: @escaping (_ previous: V, _ current: V) -> Void
) -> some View where V: Equatable {
if #available(iOS 17, *) {
onChange(of: value, action)
} else {
onChange(of: value) { [value] newValue in
action(value, newValue)
}
}
}
}
The [value] capture list preserves the old value at the moment onChange is attached.
Practical Extension: onTransition
1
2
3
4
5
6
7
8
9
10
11
12
13
public extension View {
func onTransition<V: Equatable>(
of value: V,
from reference: V,
perform action: @escaping () -> Void
) -> some View {
onChangeCompat(for: value) { oldValue, newValue in
if oldValue == reference && newValue != reference {
action()
}
}
}
}
Triggers action when value moves away from a specific state:
1
2
3
4
5
6
@State private var loadingState: LoadingState = .loading
Text("Data")
.onTransition(of: loadingState, from: .loading) {
hapticFeedback.success()
}
What do you think about this solution? Let me know in the comments!
☕ Support My Work
If you found this post helpful and want to support more content like this, you can buy me a coffee!
Your support helps me continue creating useful articles and tips for fellow developers. Thank you! 🙏
This post is licensed under CC BY 4.0 by the author.