diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 58af8a7..a3ad7ab 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -5,32 +5,30 @@ on: [push, pull_request, workflow_dispatch]
jobs:
xcode-tests:
name: "Test"
- runs-on: macOS-latest
+ runs-on: macOS-11
strategy:
matrix:
platform: [macOS, iOS, tvOS]
include:
- platform: macOS
- sdk: macosx
+ sdk: macosx11.3
destination: "arch=x86_64"
- platform: iOS
- sdk: iphonesimulator
- destination: "name=iPhone 11"
+ sdk: iphoneos15.0
+ destination: "name=iPhone 13"
- platform: tvOS
- sdk: appletvsimulator
+ sdk: appletvsimulator15.0
destination: "name=Apple TV"
steps:
- uses: actions/checkout@v2
- - name: Select Xcode 12 (beta)
- run: sudo xcode-select -s /Applications/Xcode_12_beta.app
- - name: Generate project
- run: make project
+ - name: Select Xcode 13
+ run: sudo xcode-select -s /Applications/Xcode_13.0.app
- name: Run tests
- run: set -o pipefail && xcodebuild -project CombineExt.xcodeproj -scheme CombineExt-Package -enableCodeCoverage YES -sdk ${{ matrix.sdk }} -destination "${{ matrix.destination }}" test | xcpretty -c -r html --output logs/${{ matrix.platform }}.html
+ run: set -o pipefail && xcodebuild -scheme CombineExt-Package -enableCodeCoverage YES -sdk ${{ matrix.sdk }} -destination "${{ matrix.destination }}" test | xcpretty -c -r html --output logs/${{ matrix.platform }}.html
- uses: codecov/codecov-action@v1.0.13
with:
token: 1519d58c-6fb9-483f-af6c-7f6f0b384345
@@ -39,12 +37,3 @@ jobs:
with:
name: build-logs-${{ github.run_id }}
path: logs
-
- SPM:
- name: "Test (SPM)"
- runs-on: macOS-latest
-
- steps:
- - uses: actions/checkout@v2
- - name: Run tests
- run: set -o pipefail && swift test
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/CombineExt.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/CombineExt.xcscheme
new file mode 100644
index 0000000..b833217
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/CombineExt.xcscheme
@@ -0,0 +1,91 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CombineExt.podspec b/CombineExt.podspec
index 0e266a4..5856c9d 100644
--- a/CombineExt.podspec
+++ b/CombineExt.podspec
@@ -18,5 +18,5 @@ Pod::Spec.new do |s|
s.source = { :git => "https://github.com/CombineCommunity/CombineExt.git", :tag => s.version }
s.source_files = 'Sources/**/*.swift'
s.frameworks = ['Combine']
- s.swift_version = '5.1'
+ s.swift_version = '5.5'
end
diff --git a/README.md b/README.md
index 3f6b169..f16e84b 100644
--- a/README.md
+++ b/README.md
@@ -755,6 +755,101 @@ subscription = ints
.finished
```
+------
+
+### fromAsync(priority:_:)
+
+Creates a Combine Publisher from an async function. The Publisher emits a value and then completes when the async function returns its result.
+The task that supports the async function is canceled when the publisher's subscription is canceled.
+An optional priority indicates the priority of the Task supporting the execution of the async function.
+
+```swift
+var value: Int {
+ get async {
+ 3
+ }
+}
+
+Publishers
+ .fromAsync {
+ await value
+ }.sink {
+ print($0)
+ } receiveValue: {
+ print($0)
+ }
+```
+
+#### Output:
+
+```none
+3
+finished
+```
+
+------
+
+### fromThrowingAsync(priority:_:)
+
+Creates a Combine Publisher from a throwing async function
+The Publisher emits a value and completes or fail according the the async function execution result.
+The task that supports the async function is canceled when the publisher's subscription is canceled.
+An optional priority indicates the priority of the Task supporting the execution of the async function.
+
+```swift
+struct MyError: Error, CustomStringConvertible {
+ var description: String {
+ "Async Error"
+ }
+ }
+
+Publishers
+ .fromAsync { () async throws -> String in
+ throw MyError()
+ }.sink {
+ print($0)
+ } receiveValue: {
+ print($0)
+ }
+```
+
+#### Output:
+
+```none
+failure(Async Error)
+```
+
+### fromAsyncSequence(priority:_:)
+
+Creates a Combine Publisher from an async sequence.
+The Publisher emits values or fail according the the async sequence execution result.
+An optional priority indicates the priority of the Task supporting the execution of the async sequence.
+
+```swift
+let sequence = AsyncStream(Int.self) { continuation in
+ continuation.yield(1)
+ continuation.yield(2)
+ continuation.yield(3)
+ continuation.finish()
+}
+
+Publishers
+ .fromAsyncSequence(sequence).sink {
+ print($0)
+ } receiveValue: {
+ print($0)
+ }
+```
+
+#### Output:
+
+```none
+1
+2
+3
+finished
+```
+
## Publishers
This section outlines some of the custom Combine publishers CombineExt provides
diff --git a/Sources/Operators/FromAsync.swift b/Sources/Operators/FromAsync.swift
new file mode 100644
index 0000000..0349fde
--- /dev/null
+++ b/Sources/Operators/FromAsync.swift
@@ -0,0 +1,191 @@
+//
+// FromAsync.swift
+// CombineExt
+//
+// Created by Thibault Wittemberg on 2021-06-15.
+// Copyright © 2021 Combine Community. All rights reserved.
+//
+
+#if canImport(Combine)
+import Combine
+
+@available(macOS 12.0, iOS 15.0, tvOS 15.0, watchOS 8.0, *)
+public extension Publishers {
+ /// Creates a Combine Publisher from an async function
+ /// The Publisher emits a value and then completes when the async function returns its result.
+ /// The task that supports the async function is canceled when the publisher's subscription is canceled.
+ /// ```
+ /// var value: Int {
+ /// get async {
+ /// 3
+ /// }
+ /// }
+ ///
+ /// Publishers
+ /// .fromAsync {
+ /// await value
+ /// }.sink {
+ /// print($0)
+ /// } receiveValue: {
+ /// print($0)
+ /// }
+ ///
+ /// // will print:
+ /// // 3
+ /// // finished
+ /// ```
+ /// - parameter priority: Optional value indicating the priority of the Task supporting the execution of the async function
+ /// - Returns: The Combine Publisher wrapping the async function execution
+ static func fromAsync