Created
August 12, 2022 18:00
-
-
Save atierian/c7c78e7c37c79dab98e68c6b35865b41 to your computer and use it in GitHub Desktop.
Subscribing to AsyncSequence vs Combine Publisher
This file contains hidden or 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
actor Counter: AsyncSequence { | |
typealias Element = Int | |
let limit: Int | |
var current = 1 | |
init(limit: Int, current: Int = 1) { | |
self.limit = limit | |
self.current = current | |
} | |
func increment() { | |
current += 1 | |
} | |
nonisolated func makeAsyncIterator() -> Iterator { | |
Iterator(counter: self) | |
} | |
} | |
extension Counter { | |
struct Iterator: AsyncIteratorProtocol, Sendable { | |
let counter: Counter | |
mutating func next() async -> Int? { | |
guard !Task.isCancelled else { | |
return nil | |
} | |
guard await counter.current < counter.limit else { | |
return nil | |
} | |
try! await Task.sleep(nanoseconds: 1 * NSEC_PER_SEC) | |
let result = await counter.current | |
await counter.increment() | |
return result | |
} | |
typealias Element = Int | |
} | |
} | |
struct AsyncSequenceCounterView: View { | |
let counter: Counter | |
init() { | |
counter = .init(limit: 10) | |
} | |
var body: some View { | |
Text("Hello, world!") | |
.padding() | |
.task { | |
async let sub1: () = sub1() | |
async let sub2: () = sub2() | |
await [sub1, sub2] | |
} | |
} | |
func sub1() async { | |
print(#function, "called") | |
for try await count in counter { | |
print("sub1", count) | |
} | |
} | |
func sub2() async { | |
print(#function, "called") | |
for try await count in counter { | |
print("sub2", count) | |
} | |
} | |
} |
This file contains hidden or 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
sub1() called | |
sub2() called | |
sub2 1 | |
sub1 2 | |
sub2 3 | |
sub1 4 | |
sub1 5 | |
sub2 6 | |
sub1 7 | |
sub2 8 | |
sub1 9 | |
sub2 10 |
This file contains hidden or 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 Combine | |
class PublisherCounterViewModel: ObservableObject { | |
@Published var current = 1 | |
let limit: Int | |
var cancellables = Set<AnyCancellable>() | |
var timer: Timer? | |
init(limit: Int) { | |
self.limit = limit | |
timer = Timer.scheduledTimer( | |
withTimeInterval: 1, | |
repeats: true | |
) { _ in | |
if self.current < limit { | |
DispatchQueue.main.async { | |
self.current += 1 | |
} | |
} else { | |
self.timer = nil | |
} | |
} | |
} | |
} | |
struct PublisherCounterView: View { | |
let viewModel = PublisherCounterViewModel(limit: 10) | |
var body: some View { | |
Text("Hello, world!") | |
.padding() | |
.task { | |
sub1() | |
sub2() | |
} | |
} | |
func sub1() { | |
print(#function, "called") | |
viewModel.$current.sink { count in | |
print("sub1", count) | |
} | |
.store(in: &viewModel.cancellables) | |
} | |
func sub2() { | |
print(#function, "called") | |
viewModel.$current.sink { count in | |
print("sub2", count) | |
} | |
.store(in: &viewModel.cancellables) | |
} | |
} |
This file contains hidden or 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
sub1() called | |
sub1 1 | |
sub2() called | |
sub2 1 | |
sub1 2 | |
sub2 2 | |
sub1 3 | |
sub2 3 | |
sub1 4 | |
sub2 4 | |
sub1 5 | |
sub2 5 | |
sub1 6 | |
sub2 6 | |
sub1 7 | |
sub2 7 | |
sub1 8 | |
sub2 8 | |
sub1 9 | |
sub2 9 | |
sub1 10 | |
sub2 10 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment