I have the following function loadData
and I want to use it within refreshable
of a SwiftUI list. For this I need to make it an async
function:
func loadData() {
// Publishers
let followersPublisher = modelLoader.loadAllFollowers(withId: id)
let followingPublisher = modelLoader.loadAllFollowing(withId: id)
let friendshipsPublisher = Publishers.Zip(followersPublisher, followingPublisher)
.share()
.eraseToAnyPublisher()
// Sinks
getFollowers(from: followersPublisher)
getFollowerChange(
from: followersPublisher,
cachedFollowers: followers
)
getFollowing(from: followingPublisher)
getNotFollowingUserBack(from: friendshipsPublisher)
getUserNotFollowing(from: friendshipsPublisher)
followersPublisher
.connect()
.store(in: &cancellables)
followingPublisher
.connect()
.store(in: &cancellables)
}
Within this function, all the separate functions use Publisher
sinks. For example:
private func getFollowing(from publisher: Publishers.MakeConnectable<AnyPublisher<Set<User>, Never>>) {
publisher
.sink(
receiveCompletion: { _ in },
receiveValue: { [weak self] following in
self?.following = following
}
)
.store(in: &cancellables)
}
How can I turn it into an async
function so I can use await
with it?
CodePudding user response:
Every Combine Publisher has a values
property that is an async sequence:
https://developer.apple.com/documentation/combine/publisher/values-1dm9r
Thus any pipeline that starts with a Publisher can be replaced by async/await
code, capturing the values
using an async
for loop. So if you want to, you could keep on using your followersPublisher
and your followingPublisher
and just subscribe to them using async/await
instead of Combine.
On the other hand, depending what those publishers do, you might want to follow this chain further back and get rid of those publishers and replace them by async
methods that you can call from an async/await
context.