-
-
Save jegnux/c3aee7957f6c372bf31a46c893a6e2a2 to your computer and use it in GitHub Desktop.
| import SwiftUI | |
| import Combine | |
| 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, *) { | |
| 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, *) { | |
| onChange(of: value, perform: action) | |
| } else { | |
| modifier(ChangeObserver(newValue: value, action: action)) | |
| } | |
| } | |
| } |
Also i'm getting [SwiftUI] Modifying state during view update, this will cause undefined behavior. on line 27, which is fixable by adding .receive(on: DispatchQueue.main) operator to the Just on line 13
-> .onReceive(Just(newValue).receive(on: DispatchQueue.main)) { newValue in
+1 To what is the purpose of onAppear
@KoCMoHaBTa @kuanfajardo I don't remember well but it was probably a workaround to some bug.
This is such a beautiful solution...... wow......
Great solution! Saved me. Just one question: What's the idea of putting action into state? Seems, the action never changes within the struct lifecycle
@subtranix my backports library actually has some improvements and is far more battle tested against a lot more projects id suggest checking that out.
What is the purpose of the
onAppear()on line 22?