-
-
Save tonyarnold/952957eccc7fad09fa12e506cbf9bbe6 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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