Reputation: 10330
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
Upvotes: 1
Views: 2533
Reputation: 10330
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) }
}
}
Upvotes: 1