Created
March 14, 2024 10:44
-
-
Save mattmassicotte/2737e6de5398d890e6de468fc0f51d76 to your computer and use it in GitHub Desktop.
AsyncChanges
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 | |
import AsyncAlgorithms | |
struct AsyncChanges<V>: ViewModifier where V : Equatable, V: Sendable { | |
typealias Element = (oldValue: V, newValue: V) | |
typealias Action = (AsyncStream<Element>) async -> Void | |
@State private var streamPair = AsyncStream<Element>.makeStream() | |
private let action: Action | |
private let value: V | |
init(of value: V, initial: Bool, action: @escaping Action) { | |
self.action = action | |
self.value = value | |
} | |
func body(content: Content) -> some View { | |
content | |
.onChange(of: value, initial: true) { oldValue, newValue in | |
streamPair.continuation.yield((oldValue, newValue)) | |
} | |
.task { | |
await action(streamPair.stream) | |
} | |
} | |
} | |
extension View { | |
public func asyncChanges<V>( | |
of value: V, | |
initial: Bool = false, | |
action: @escaping (AsyncStream<(oldValue: V, newValue: V)>) async -> Void | |
) -> some View where V: Equatable, V: Sendable { | |
modifier(AsyncChanges<V>(of: value, initial: initial, action: action)) | |
} | |
} | |
struct ContentView: View { | |
@State private var username = "" | |
var body: some View { | |
TextField("Username", text: self.$username) | |
.asyncChanges(of: username) { sequence in | |
for await value in sequence.debounce(for: .seconds(0.25)) { | |
print("debounced value: \(value.newValue)") | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment