iOS 13-compatible backports of commonly used async/await-based system APIs that are only available from iOS 15 by default.

Overview

AsyncCompatibilityKit

Welcome to AsyncCompatibilityKit, a lightweight Swift package that adds iOS 13-compatible backports of commonly used async/await-based system APIs that are only available from iOS 15 by default.

It currently includes backward compatible versions of the following APIs:

  • URLSession.data(from: URL)
  • URLSession.data(for: URLRequest)
  • Combine.Publisher.values
  • SwiftUI.View.task

All of the included backports have signatures matching their respective system APIs, so that once you’re ready to make iOS 15 your minimum deployment target, you should be able to simply unlink AsyncCompatibilityKit from your project without having to make any additional changes to your code base (besides removing all import AsyncCompatibilityKit statements).

AsyncCompatibilityKit even marks all of its added APIs as deprecated when integrated into an iOS 15-based project, so that you’ll get a reminder that it’s no longer needed once you’re able to use the matching system APIs directly (as of Xcode 13.2, no such deprecation warnings seem to show up within SwiftUI views, though).

However, it’s important to point out that the implementations provided by AsyncCompatibilityKit might not perfectly match their system equivalents in terms of behavior, since those system implementations are closed-source and private to Apple. No reverse engineering was involved in writing this library. Instead, each of the included APIs are complete reimplementations of the system APIs that they’re intended to match. It’s therefore strongly recommended that you thoroughly test any code that uses these backported versions before deploying that code to production.

To learn more about the techniques used to implement these backports, and Swift Concurrency in general, check out Discover Concurrency over on Swift by Sundell.

Installation

AsyncCompatibilityKit is distributed using the Swift Package Manager. To install it, use Xcode’s File > Add Packages... menu command to add it to your iOS app project.

Then import AsyncCompatibilityKit wherever you’d like to use it:

import AsyncCompatibilityKit

For more information on how to use the Swift Package Manager, check out this article, or its official documentation.

Please note that AsyncCompatibilityKit is not meant to be integrated into targets other than iOS app projects with a minimum deployment target of iOS 13 or above. It also requires Xcode 13.2 or later.

Support and contributions

AsyncCompatibilityKit has been made freely available to the entire Swift community under the very permissive MIT license, but please note that it doesn’t come with any official support channels, such as GitHub issues, or Twitter/email-based support. So, before you start using AsyncCompatibilityKit within one of your projects, it’s highly recommended that you spend some time familiarizing yourself with its implementation, in case you’ll run into any issues that you’ll need to debug.

If you’ve found a bug, documentation typo, or if you want to propose a performance improvement, then feel free to open a Pull Request (even if it just contains a unit test that reproduces a given issue). While all sorts of fixes and tweaks are more than welcome, AsyncCompatibilityKit is meant to be a very small, focused library, and should only contain simple backports of async/await-based system APIs. So, if you’d like to add any significant new features to the library, then it’s recommended that you fork it, which will let you extend and customize it to fit your needs.

Hope you’ll enjoy using AsyncCompatibilityKit!

Comments
  • Fix an issue leading to non-cancelled action

    Fix an issue leading to non-cancelled action

    When onDisappear is called, it might try to cancel a non-existing task when the view body has been re-evaluated between onAppear and onDisappear. Storing the task in a @State fixes this issue.

    As showcased in the following video, this fix should now behave like the iOS 15+ task { ... } modifier.

    Screen Shot 2021-12-20 at 16 35 50

    opened by jegnux 1
  • Make SwiftUI task modifier cancel the correct task after updates

    Make SwiftUI task modifier cancel the correct task after updates

    Turn the task generated by the SwiftUI task modifier into a State property, so that it's retained across view updates, and so that the correct task is cancelled if the view disappears before the task has been completed.

    opened by JohnSundell 0
  • URLSession: Cancel underlying data task when parent task is cancelled

    URLSession: Cancel underlying data task when parent task is cancelled

    Use the withTaskCancellationHandler function to get access to a cancellation handler, within which we can then cancel the underlying URLSessionDataTask that's used to perform the actual network call.

    opened by JohnSundell 0
  • Support immediate data task cancellation

    Support immediate data task cancellation

    While testing my unit tests (which were working fine on iOS 15) with the back ported version of URLSession.data(for:) from AsyncCompatibilityKit the cancelation test stopped working even though the package implements task cancellation.

    So I was analyzing the issue and found, that task cancellations immediately following the task creation were not considered because the URLSessionDataTask was not yet created, therefore the dataTask was nil.

    So I've implemented a shouldCancel flag which is set by the onCancel handler and considered before resuming the task.

    I hope this is also useful to other library users.

    opened by pd95 1
  • Download

    Download

    Add download tasks

    • Note, though, that unlike the data task, I made the method name distinct (using with rather than for/from).
    • Should the data task also use unique names rather than counterfeiting the iOS 15 method names?
    • This uses the actor pattern referenced in my other pull request.
    • If you approve of this pull request, I'm happy to do an upload task rendition, too.
    opened by robertmryan 2
  • Actor

    Actor

    • The use of the onCancel closure is hiding the fact that the completion handler is @Sendable, whereas onCancel is not.
    • If you define onCancel to be @Sendable, it reintroduces the compiler warning.
    • I suspect that the closure pattern was used to eliminate the compiler warning, but I believe you are simply eliminating the warning, but not fixing the problem that the compiler was warning us about.
    • Instead, use an actor to ensure thread-safe interaction with the URLSessionTask.
    opened by robertmryan 5
  • Add

    Add "support" for iOS < 13

    I'm trying to use this in a package that needs to be compatible with iOS 12, but simply integrating AsyncCompatibilityKit results in an error:

    Screenshot 2021-12-24 at 07 22 06

    The fix: Add introduced: 13.0 to the @available statements: This way, consumers can import the package on iOS <13 (where it does nothing).

    opened by xavierLowmiller 0
  • Add support for macOS

    Add support for macOS

    Thank you for this! I used this in a multiplatform test project. I needed to change a few things for macOS support.

    • Change package platforms to support Catalina and above
    • Add macOS availability annotation with deprecation for Monterey
    • Adjust showView helper for running tests on macOS

    I also noticed that some of the tests are flaky with Xcode 13.2 on 11.6.2. It can be reproduced easily with the repeated tests feature in Xcode.

    Example:

    let subject = PassthroughSubject<Int, Never>()
    
    let valueTask = Task<[Int], Never> {
      var values = [Int]()
    
      for await value in subject.values {
        values.append(value)
      }
    
      return values
    }
    
    Task {
      subject.send(1)
      subject.send(2)
      subject.send(3)
      subject.send(completion: .finished)
    }
    
    let values = await valueTask.value
    XCTAssertEqual(values, [1, 2, 3])
    

    Mac (11.6.2) as test platform:

    Test Suite 'AsyncCompatibilityKitTests.xctest' failed at 2021-12-22 15:37:33.281.
    	 Executed 100 tests, with 20 failures (0 unexpected) in 5.906 (6.114) seconds
    

    It seems that the Task that sends the values and the finish event to the subject might run before the valueTask and then only the completion is received resulting in an empty array. Adding a short Task.sleep before sending the values fixes this as a workaround. I'm still learning how the new swift concurrency works. But I'm not sure about any guarantees for the order of execution of the two Task { } blocks here. The PassthroughSubject will drop values, if there's no subscriber yet.

    Testing repeatedly on iOS simulators with iOS 13.7 or 14.5 also fails.

    opened by KaiOelfke 1
Releases(0.1.2)
  • 0.1.2(Dec 20, 2021)

    Fixed an issue that could cause the task SwiftUI modifier not to cancel the correct task when its view disappeared after a state update (thanks to @jegnux for helping out with the fix for this issue).

    Source code(tar.gz)
    Source code(zip)
  • 0.1.1(Dec 17, 2021)

    When performing a network call using the async-marked URLSession methods that AsyncCompatibilityKit provides, cancelling such an operation's parent Task now also cancels that network call.

    Source code(tar.gz)
    Source code(zip)
  • 0.1.0(Dec 17, 2021)

Owner
John Sundell
I build apps, games and Swift developer tools! Passionate about open source & developer productivity. You can follow me on Twitter @JohnSundell.
John Sundell
Example project showing how to use async/await with iOS 13

ios13AsyncAwait Example project showing how to use async/await with iOS 13 Article This source code is a part of an article published at This Dev Brai

Michał Tynior 7 Oct 2, 2022
Using async / await on iOS 13: everything you need to know

Using async / await on iOS 13: everything you need to know! ?? Content This repository contains the code sample I've used during December 14th's lives

Vincent Pradeilles 11 Feb 1, 2022
Lightweight async/await networking library with interceptor support - usable from iOS 13+.

Lightweight async/await networking library with interceptor support. ?? Getting started AsyncNetwork's session acts as a wrapper to URLSession by addi

Paul 9 Oct 4, 2022
Hydra ⚡️ Lightweight full-featured Promises, Async & Await Library in Swift

Lightweight full-featured Promises, Async & Await Library in Swift What's this? Hydra is full-featured lightweight library which allows you to write b

Daniele Margutti 2k Dec 24, 2022
⏳ Collection of Swift 5.5 async/await utility functions.

⏳ FunAsync Collection of Swift 5.5 async/await utility functions. Throw <-> Result conversion asyncThrowsToAsyncResult asyncResultToAsyncThrows More C

Yasuhiro Inami 23 Oct 14, 2022
🎭 Swift async/await & Actor-powered effectful state-management framework.

?? Actomaton ??‍?? Actor + ?? Automaton = ?? Actomaton Actomaton is Swift async/await & Actor-powered effectful state-management framework inspired by

Yasuhiro Inami 199 Dec 20, 2022
A lightweight swift network layer with Combine, Async-Await, and a traditional completion block.

CombineNetwork A simple light-weight network library to make network requesting simpler. It supports newer techonology such as async/await as well as

Dushant Singh 4 Jan 3, 2022
Hydra: Lightweight full-featured Promises, Async-Await Library in Swift

Async Functions for ECMAScript The introduction of Promises and Generators in EC

Ecma TC39 1.6k Oct 17, 2022
straightforward networking and error handling with async-await and URLSession

AsyncAwaitNetworkingPlayground How To Run Just clone the project, open it and run. Some notes about AsyncAwaitNetworkingPlayground It's a straightforw

Fırat Yenidünya 17 Dec 11, 2022
AsyncTaskKit - contains some additions to async/await Task

AsyncTaskKit This repo contains some additions to async/await Task. In general i

Michał Zaborowski 0 Jan 2, 2022
AsyncLocationKit - Async/await CoreLocation With Swift

AsyncLocationKit Wrapper for Apple CoreLocation framework with new Concurency Mo

AsyncSwift 89 Dec 30, 2022
Edit images and video with async / await in Swift, powered by Metal.

AsyncGraphics The core value type in AsyncGraphics is a Graphic. It's like an image, tho it can be used with various async methods. Documentation Swif

Anton Heestand 33 Dec 27, 2022
A Swift lib for network with async/await

SmileNetwork A Swift network utility with async/await applied UseAge enum MockEndpoint { case weather(cityId: String) } extension MockEndpoint: S

null 2 Jul 13, 2022
Test app for the InStat company. The project uses MVVM architecture, interface created with SwiftUI, network requests with async/await

FootStats Test app for the InStat company. The Project uses MVVM architecture, interface created with SwiftUI, network requests with async/await using

Nizami Tagiyev 4 Dec 15, 2022
Async and concurrent versions of Swift’s forEach, map, flatMap, and compactMap APIs.

CollectionConcurrencyKit Welcome to CollectionConcurrencyKit, a lightweight Swift package that adds asynchronous and concurrent versions of the standa

John Sundell 684 Jan 9, 2023
A general purpose embedded hierarchical lock manager used to build highly concurrent applications of all types. Same type of locker used in many of the large and small DBMSs in existence today.

StickyLocking StickyLocking is a general purpose embedded lock manager which allows for locking any resource hierarchy. Installable Lock modes allow f

Sticky Tools 2 Jun 15, 2021
⚡️ Fast async task based Swift framework with focus on type safety, concurrency and multi threading

Our apps constantly do work. The faster you react to user input and produce an output, the more likely is that the user will continue to use your appl

Said Sikira 814 Oct 30, 2022
Syntactic sugar in Swift for asynchronous dispatches in Grand Central Dispatch (iOS7+ and OS X 10.9+ compatible)

Async.legacy Syntactic sugar in Swift for asynchronous dispatches in Grand Central Dispatch (GCD) Async rewritten for iOS7 and OS X 10.9 Compatibility

Joseph Lord 31 Jul 1, 2019
React Native FlyBuy module. Supports Core, Pickup, Notify, and Presence Native SDK APIs.

The FlyBuy cloud service and mobile SDK enables developers to add FlyBuy functionality directly into their react native apps for a full white label im

BILDIT, LLC. 8 Sep 16, 2022