Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save tonyarnold/952957eccc7fad09fa12e506cbf9bbe6 to your computer and use it in GitHub Desktop.
Save tonyarnold/952957eccc7fad09fa12e506cbf9bbe6 to your computer and use it in GitHub Desktop.
import SwiftUI
public struct ChangeObserver<V: Equatable>: ViewModifier {
public init(newValue: V, action: @escaping (V) -> Void) {
self.newValue = newValue
self.newAction = action
}
private typealias Action = (V) -> Void
private let newValue: V
private let newAction: Action
@State private var state: (V, Action)?
public func body(content: Content) -> some View {
if #available(iOS 14, macOS 11, watchOS 7, *) {
assertionFailure("Please don't use this ViewModifer directly and use the `onChange(of:perform:)` modifier instead.")
}
return content
.onAppear()
.onReceive(Just(newValue)) { newValue in
if let (currentValue, action) = state, newValue != currentValue {
action(newValue)
}
state = (newValue, newAction)
}
}
}
extension View {
@_disfavoredOverload
@ViewBuilder public func onChange<V>(of value: V, perform action: @escaping (V) -> Void) -> some View where V: Equatable {
if #available(iOS 14, macOS 11, watchOS 7, *) {
onChange(of: value, perform: action)
} else {
modifier(ChangeObserver(newValue: value, action: action))
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment