'Using Combine Publisher with AsyncSequence
I'm currently migrating code that was using Combine Publisher to an AsyncSequence. I previously used this alongside @Published search query that user could type in and now trying to "combine" that search term with AsyncSequence based data source such as following (using values to convert the search query to AsyncSequence as well). However, I'm only seeing the flatMap code being executed once initially.
@MainActor
class FantasyPremierLeagueViewModel: ObservableObject {
@Published var playerList = [Player]()
@Published var query: String = ""
private let repository: FantasyPremierLeagueRepository
init(repository: FantasyPremierLeagueRepository) {
self.repository = repository
Task {
let playerStream = asyncStream(for: repository.playerListNative)
let filteredPlayerStream = $query
.debounce(for: 0.5, scheduler: DispatchQueue.main)
.values
.flatMap { query in
playerStream
.map { $0.filter { uery.isEmpty || $0.name.contains(query) } }
}
.map { $0.sorted { $0.points > $1.points } }
for try await data in filteredPlayerStream {
self.playerList = data
}
}
}
}
Code pushed to branch and can also be viewed in https://github.com/joreilly/FantasyPremierLeague/blob/kmp_native_coroutines/ios/FantasyPremierLeague/FantasyPremierLeague/ViewModel.swift
Solution 1:[1]
Ok, looks like this can be done in a much cleaner way using combineLatest() from new Swift Async Algorithms package (https://github.com/apple/swift-async-algorithms).
Task {
let playerStream = asyncStream(for: repository.playerListNative)
.map { $0.sorted { $0.points > $1.points } }
for try await (players, searchQuery) in combineLatest(playerStream, $query.values) {
self.playerList = players
.filter { searchQuery.isEmpty || $0.name.localizedCaseInsensitiveContains(query) }
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | John O'Reilly |
