Skip to content

Repository files navigation

Asynchrone

Extensions and additions for Swift's async sequence.

Requirements

  • iOS 14.0+
  • macOS 12.0+
  • watchOS 6.0+
  • tvOS 14.0+

Installation

Swift Package Manager

In Xcode:

  1. Click Project.
  2. Click Package Dependencies.
  3. Click +.
  4. Enter package URL: https://github.com/reddavis/Asynchrone.
  5. Add Asynchrone to your app target.

Documentation

Documentation can be found here.

Overview

AsyncSequence

Extensions

Assign

classMyClass{varvalue:Int=0{
didSet {print("Set to \(self.value)")}}}letsequence= AsyncStream<Int>{ continuation in
continuation.yield(1)
continuation.yield(2)
continuation.yield(3)
continuation.finish()}letobject=MyClass()
sequence.assign(to: \.value, on: object)
// Prints:
// Set to 1
// Set to 2
// Set to 3

First

letsequence= AsyncStream<Int>{ continuation in
continuation.yield(1)
continuation.yield(2)
continuation.yield(3)
continuation.finish()}print(await sequence.first())
// Prints:
// 1

Last

letsequence= AsyncStream<Int>{ continuation in
continuation.yield(1)
continuation.yield(2)
continuation.yield(3)
continuation.finish()}print(await sequence.last())
// Prints:
// 3

Collect

letsequence= AsyncStream<Int>{ continuation in
continuation.yield(1)
continuation.yield(2)
continuation.yield(3)
continuation.finish()}print(await sequence.collect())
// Prints:
// [1, 2, 3]

Sink

letsequence=.init { continuation in
continuation.yield(1)
continuation.yield(2)
continuation.yield(3)
continuation.finish()}
sequence.sink{print($0)}
// Prints:
// 1
// 2
// 3

Sink with completion

letsequence=.init { continuation in
continuation.yield(1)
continuation.yield(2)
continuation.yield(3)
continuation.finish(throwing:TestError())}
sequence.sink(
receiveValue:{print("Value: \($0)")},
receiveCompletion:{print("Complete: \($0)")})
// Prints:
// Value: 1
// Value: 2
// Value: 3
// Complete: failure(TestError())
letsequence=Just(1).map(String.init).eraseToAnyAsyncSequenceable()
letstream=Fail<Int,TestError>(error:TestError.a).eraseToAnyThrowingAsyncSequenceable()
letsequence=Fail<Int,TestError>(
error:TestError()).catch{ error inJust(-1)}forawaitvaluein sequence {print(value)}
// Prints:
// -1
letsequenceA= AsyncStream<Int>{ continuation in
continuation.yield(1)
continuation.yield(2)
continuation.yield(3)
continuation.finish()}letsequenceB= AsyncStream<Int>{ continuation in
continuation.yield(4)
continuation.yield(5)
continuation.yield(6)
continuation.finish()}letsequenceC= AsyncStream<Int>{ continuation in
continuation.yield(7)
continuation.yield(8)
continuation.yield(9)
continuation.finish()}forawaitvaluein sequenceA.chain(with: sequenceB).chain(with: sequenceC){print(value)}
// Prints:
// 1
// 2
// 3
// 4
// 5
// 6
// 7
// 8
// 9
letstreamA=.init { continuation in
continuation.yield(1)
continuation.yield(2)
continuation.yield(3)
continuation.yield(4)
continuation.finish()}letstreamB=.init { continuation in
continuation.yield(5)
continuation.yield(6)
continuation.yield(7)
continuation.yield(8)
continuation.yield(9)
continuation.finish()}forawaitvaluein streamA.combineLatest(streamB){print(value)}
// Prints:
// (1, 5)
// (2, 6)
// (3, 7)
// (4, 8)
// (4, 9)
letstreamA=.init { continuation in
continuation.yield(1)
continuation.yield(2)
continuation.yield(3)
continuation.yield(4)
continuation.finish()}letstreamB=.init { continuation in
continuation.yield(5)
continuation.yield(6)
continuation.yield(7)
continuation.yield(8)
continuation.yield(9)
continuation.finish()}letstreamC=.init { continuation in
continuation.yield(10)
continuation.yield(11)
continuation.finish()}forawaitvaluein streamA.combineLatest(streamB, streamC){print(value)}
// Prints:
// (1, 5, 10)
// (2, 6, 11)
// (3, 7, 11)
// (4, 8, 11)
// (4, 9, 11)
letsequence=CurrentElementAsyncSequence(0)print(await sequence.element)await stream.yield(1)print(await sequence.element)await stream.yield(2)await stream.yield(3)await stream.yield(4)print(await sequence.element)
// Prints:
// 0
// 1
// 4
letstream= AsyncStream<Int>{ continuation in
continuation.yield(0)try?awaitTask.sleep(nanoseconds:200_000_000)
continuation.yield(1)try?awaitTask.sleep(nanoseconds:200_000_000)
continuation.yield(2)
continuation.yield(3)
continuation.yield(4)
continuation.yield(5)
continuation.finish()}
for element in tryawaitself.stream.debounce(for:0.1){print(element)}
// Prints:
// 0
// 1
// 5
letstream= AsyncStream<Int>{ continuation in
continuation.yield(0)
continuation.yield(1)
continuation.yield(2)
continuation.finish()}letstart=Date.now
for element in tryawaitself.stream.delay(for:0.5){print("\(element) - \(Date.now.timeIntervalSince(start))")}
// Prints:
// 0 - 0.5
// 1 - 1.0
// 2 - 1.5
>>>>>>> main
Empty<Int>().sink(
receiveValue:{print($0)},
receiveCompletion:{ completion inswitch completion {case.finished:print("Finished")case.failure:print("Failed")}})
// Prints:
// Finished
letstream=Fail<Int,TestError>(error:TestError())do{fortryawaitvaluein stream {print(value)}}catch{print("Error!")}
// Prints:
// Error!
letstream=Just(1)forawaitvaluein stream {print(value)}
// Prints:
// 1
letstreamA=.init { continuation in
continuation.yield(1)
continuation.yield(2)
continuation.yield(3)
continuation.yield(4)
continuation.finish()}letstreamB=.init { continuation in
continuation.yield(5)
continuation.yield(6)
continuation.yield(7)
continuation.yield(8)
continuation.yield(9)
continuation.finish()}forawaitvaluein streamA.merge(with: streamB){print(value)}
// Prints:
// 1
// 5
// 2
// 6
// 3
// 7
// 4
// 8
// 9
letstreamA=.init { continuation in
continuation.yield(1)
continuation.yield(4)
continuation.finish()}letstreamB=.init { continuation in
continuation.yield(2)
continuation.finish()}letstreamC=.init { continuation in
continuation.yield(3)
continuation.finish()}forawaitvalueinself.streamA.merge(with:self.streamB,self.streamC){print(value)}
// Prints:
// 1
// 2
// 3
// 4
letsequence=NotificationCenter.default.sequence(for:UIDevice.orientationDidChangeNotification)forawaitelementin sequence {print(element)}
letsequence=PassthroughAsyncSequence<Int>()
sequence.yield(0)
sequence.yield(1)
sequence.yield(2)
sequence.finish()forawaitvaluein sequence {print(value)}
// Prints:
// 0
// 1
// 2
letstream=.init { continuation in
continuation.yield(1)
continuation.yield(1)
continuation.yield(2)
continuation.yield(3)
continuation.finish()}forawaitvaluein stream.removeDuplicates(){print(value)}
// Prints:
// 1
// 2
// 3
letsequence=Fail<Int,TestError>(
error:TestError()).replaceError(with:0)forawaitvaluein stream {print(value)}
// Prints:
// 0
letsequence=[0,1,2,3].asyncforawaitvaluein sequence {print(value)}
// Prints:
// 1
// 2
// 3
letvalues=["a","ab","abc","abcd"]letstream=AsyncStream{ continuation inforvaluein values {
continuation.yield(value)}
continuation.finish()}.shared()Task{letvalues=tryawaitself.stream.collect()
// ...
}Task.detached{letvalues=tryawaitself.stream.collect()
// ...
}letvalues=tryawaitself.stream.collect()
// ...
letstream= AsyncStream<Int>{ continuation in
continuation.yield(0)try?awaitTask.sleep(nanoseconds:100_000_000)
continuation.yield(1)try?awaitTask.sleep(nanoseconds:100_000_000)
continuation.yield(2)
continuation.yield(3)
continuation.yield(4)
continuation.yield(5)
continuation.finish()}
for element in tryawaitself.stream.throttle(for:0.05, latest:true){print(element)}
// Prints:
// 0
// 1
// 2
// 5
letsequence=ThrowingPassthroughAsyncSequence<Int>()
sequence.yield(0)
sequence.yield(1)
sequence.yield(2)
sequence.finish(throwing:TestError())do{fortryawaitvaluein sequence {print(value)}}catch{print("Error!")}
// Prints:
// 0
// 1
// 2
// Error!
letsequence=TimerAsyncSequence(interval:1)letstart=Date.now
forelementinawait sequence {print(element)}
// Prints:
// 2022-03-19 20:49:30 +0000
// 2022-03-19 20:49:31 +0000
// 2022-03-19 20:49:32 +0000
letstreamA=.init { continuation in
continuation.yield(1)
continuation.yield(2)
continuation.finish()}letstreamB=.init { continuation in
continuation.yield(5)
continuation.yield(6)
continuation.yield(7)
continuation.finish()}forawaitvaluein streamA.zip(streamB){print(value)}
// Prints:
// (1, 5)
// (2, 6)
letstreamA=.init { continuation in
continuation.yield(1)
continuation.yield(2)
continuation.finish()}letstreamB=.init { continuation in
continuation.yield(5)
continuation.yield(6)
continuation.yield(7)
continuation.finish()}letstreamC=.init { continuation in
continuation.yield(8)
continuation.yield(9)
continuation.finish()}forawaitvaluein streamA.zip(streamB, streamC){print(value)}
// Prints:
// (1, 5, 8)
// (2, 6, 9)

Other libraries

  • Papyrus - Papyrus aims to hit the sweet spot between saving raw API responses to the file system and a fully fledged database like Realm.
  • Validate - A property wrapper that can validate the property it wraps.
  • Kyu - A persistent queue system in Swift.
  • FloatingLabelTextFieldStyle - A floating label style for SwiftUI's TextField.
  • Panel - A panel component similar to the iOS Airpod battery panel.

About

Extensions and additions to AsyncSequence, AsyncStream and AsyncThrowingStream.

Topics

Resources

Stars

218 stars

Watchers

6 watching

Forks

Releases

Sponsor this project

Used by

Contributors

Languages