-
Notifications
You must be signed in to change notification settings - Fork 59
How to use SharedReaderKey with AsyncStream? #142
Unanswered
zunda-pixel
asked this question in
Q&A
-
Second AsyncStream(API project) provides realtime values([String: String]).
struct RemoteValue: SharedReaderKey { struct IDStore: Hashable { var key: String var projectUrl: URL } var id: IDStore { IDStore(key: key, projectUrl: projectUrl) } var key: String var projectUrl: URL var storage: Storage init(key: String, projectUrl: URL) { @Dependency(\.defaultStorage) var storage self.storage = storage self.key = key self.projectUrl = projectUrl } static func streamValues(url: URL) -> AsyncStream<[String: String]> { return AsyncStream { continuation in Task { for i in 1..<100000 { try? await Task.sleep(for: .seconds(1)) let fetchData: [String: String] = (0..<5).reduce( into: [String: String](), { 0ドル["\(1ドル)"] = "| \(url) | value: \(1ドル + i) |"} ) continuation.yield(fetchData) } } } } public typealias Value = String? public func load(context: LoadContext<Value>, continuation: LoadContinuation<Value>) { continuation.resumeReturningInitialValue() } public func subscribe( context: Sharing.LoadContext<Value>, subscriber: Sharing.SharedSubscriber<Value> ) -> Sharing.SharedSubscription { storage.tasks.withLock { tasks in guard tasks[projectUrl] == nil || tasks[projectUrl]?.isCancelled == true else { return } tasks[projectUrl] = Task { for await pairs in Self.streamValues(url: projectUrl) { subscriber.yield(pairs[key]) } } } return SharedSubscription { storage.tasks.withLock { tasks in tasks[projectUrl]?.cancel() } } } } final class Storage: Sendable { let tasks: Mutex<[URL: Task<Void, Never>]> = .init([:]) } enum DefaultStorageKey: DependencyKey { static var liveValue: Storage { Storage() } } struct ContentView: View { @SharedReader(.remoteValue("1", projectUrl: .project1)) var value1to1 @SharedReader(.remoteValue("2", projectUrl: .project1)) var value1to2 @SharedReader(.remoteValue("1", projectUrl: .project2)) var value2to1 @SharedReader(.remoteValue("2", projectUrl: .project2)) var value2to2 var body: some View { List { Text(value1to1 ?? "value1to1 not found") Text(value1to2 ?? "value1to2 not found") Text(value2to1 ?? "value2to1 not found") Text(value2to2 ?? "value2to2 not found") } } } extension URL { static let project1 = URL(string: "https://api.server.com/stream-remote/project1")! static let project2 = URL(string: "https://api.server.com/stream-remote/project2")! } extension SharedReaderKey { static func remoteValue(_ key: String, projectUrl: URL) -> Self where Self == RemoteValue { RemoteValue(key: key, projectUrl: projectUrl) } } extension DependencyValues { var defaultStorage: Storage { get { self[DefaultStorageKey.self] } set { self[DefaultStorageKey.self] = newValue } } } #Preview { ContentView() .frame(maxWidth: 500, maxHeight: 500) } |
Beta Was this translation helpful? Give feedback.
All reactions
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment