Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async/Await iOS 13 Support #36

Merged
merged 10 commits into from
Jan 20, 2022
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
jobs:
release:
name: Make CocoaPods release
runs-on: macOS-latest
runs-on: macos-11
steps:
- name: Checkout
uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ on:
jobs:
test:
name: Run tests
runs-on: macOS-latest
runs-on: macos-11
steps:
- name: Checkout
uses: actions/checkout@v2
Expand Down
4 changes: 2 additions & 2 deletions Sources/Apexy/Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ public protocol Client: AnyObject {

/// Send request to specified endpoint.
/// - Returns: response data from the server for the request.
@available(macOS 12, iOS 15, watchOS 8, tvOS 15, *)
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
func request<T>(_ endpoint: T) async throws -> T.Content where T: Endpoint

/// Upload data to specified endpoint.
/// - Returns: response data from the server for the upload.
@available(macOS 12, iOS 15, watchOS 8, tvOS 15, *)
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
func upload<T>(_ endpoint: T) async throws -> T.Content where T: UploadEndpoint

}
7 changes: 4 additions & 3 deletions Sources/ApexyAlamofire/AlamofireClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Copyright © 2019 RedMadRobot. All rights reserved.
//

import Apexy
subdan marked this conversation as resolved.
Show resolved Hide resolved
import Foundation
import Alamofire

Expand Down Expand Up @@ -179,7 +180,7 @@ open class AlamofireClient: Client {
return progress
}

@available(macOS 12, iOS 15, watchOS 8, tvOS 15, *)
@available(macOS 10.15, iOS 12, watchOS 6, tvOS 13, *)
public func request<T>(_ endpoint: T) async throws -> T.Content where T : Endpoint {
typealias ContentContinuation = CheckedContinuation<T.Content, Error>
let progressWrapper = ProgressWrapper()
Expand All @@ -192,7 +193,7 @@ open class AlamofireClient: Client {
})
}

@available(macOS 12, iOS 15, watchOS 8, tvOS 15, *)
@available(macOS 10.15, iOS 12, watchOS 6, tvOS 13, *)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: iOS 12 or 13?

public func upload<T>(_ endpoint: T) async throws -> T.Content where T : UploadEndpoint {
typealias ContentContinuation = CheckedContinuation<T.Content, Error>
let progressWrapper = ProgressWrapper()
Expand Down Expand Up @@ -247,7 +248,7 @@ public extension Error {
}
}

@available(macOS 12, iOS 15, watchOS 8, tvOS 15, *)
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
private final class ProgressWrapper {

var progress: Progress? {
Expand Down
73 changes: 73 additions & 0 deletions Sources/ApexyURLSession/URLSession+AsyncAwait13.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// URLSession+AsyncAwait13.swift
// ApexyURLSession
//
// Created by Aleksei Tiurnin on 20.01.2022.
//

import Foundation

extension URLSession {
@available(macOS, introduced: 10.15, deprecated: 12, message: "Extension is no longer necessary. Use API built into SDK")
@available(iOS, introduced: 13, deprecated: 15, message: "Extension is no longer necessary. Use API built into SDK")
@available(watchOS, introduced: 6, deprecated: 8, message: "Extension is no longer necessary. Use API built into SDK")
@available(tvOS, introduced: 13, deprecated: 15, message: "Extension is no longer necessary. Use API built into SDK")
func data(
for request: URLRequest,
delegate: URLSessionTaskDelegate? = nil) async throws -> (Data, URLResponse) {
try await withCheckedThrowingContinuation { continuation in
let task = self.dataTask(with: request) { data, response, error in
guard let data = data, let response = response else {
let error = error ?? URLError(.badServerResponse)
return continuation.resume(throwing: error)
}

continuation.resume(returning: (data, response))
}

task.resume()
}
}

@available(macOS, introduced: 10.15, deprecated: 12, message: "Extension is no longer necessary. Use API built into SDK")
@available(iOS, introduced: 13, deprecated: 15, message: "Extension is no longer necessary. Use API built into SDK")
@available(watchOS, introduced: 6, deprecated: 8, message: "Extension is no longer necessary. Use API built into SDK")
@available(tvOS, introduced: 13, deprecated: 15, message: "Extension is no longer necessary. Use API built into SDK")
public func upload(
for request: URLRequest,
fromFile fileURL: URL,
delegate: URLSessionTaskDelegate? = nil) async throws -> (Data, URLResponse) {
try await withCheckedThrowingContinuation { continuation in
let task = self.uploadTask(with: request, fromFile: fileURL) { data, response, error in
guard let data = data, let response = response else {
let error = error ?? URLError(.badServerResponse)
return continuation.resume(throwing: error)
}

continuation.resume(returning: (data, response))
}
task.resume()
}
}

@available(macOS, introduced: 10.15, deprecated: 12, message: "Extension is no longer necessary. Use API built into SDK")
@available(iOS, introduced: 13, deprecated: 15, message: "Extension is no longer necessary. Use API built into SDK")
@available(watchOS, introduced: 6, deprecated: 8, message: "Extension is no longer necessary. Use API built into SDK")
@available(tvOS, introduced: 13, deprecated: 15, message: "Extension is no longer necessary. Use API built into SDK")
public func upload(
for request: URLRequest,
from bodyData: Data,
delegate: URLSessionTaskDelegate? = nil) async throws -> (Data, URLResponse) {
try await withCheckedThrowingContinuation { continuation in
let task = self.uploadTask(with: request, from: bodyData) { data, response, error in
guard let data = data, let response = response else {
let error = error ?? URLError(.badServerResponse)
return continuation.resume(throwing: error)
}

continuation.resume(returning: (data, response))
}
task.resume()
}
}
}
5 changes: 3 additions & 2 deletions Sources/ApexyURLSession/URLSessionClient.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Apexy
import Foundation

open class URLSessionClient: Client {
Expand Down Expand Up @@ -127,7 +128,7 @@ open class URLSessionClient: Client {
return task.progress
}

@available(macOS 12, iOS 15, watchOS 8, tvOS 15, *)
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
open func request<T>(_ endpoint: T) async throws -> T.Content where T : Endpoint {
var request = try endpoint.makeRequest()
request = try requestAdapter.adapt(request)
Expand Down Expand Up @@ -156,7 +157,7 @@ open class URLSessionClient: Client {
}
}

@available(macOS 12, iOS 15, watchOS 8, tvOS 15, *)
@available(macOS 10.15, iOS 12, watchOS 6, tvOS 13, *)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iOS 12 or 13?

open func upload<T>(_ endpoint: T) async throws -> T.Content where T : UploadEndpoint {
var request: (request: URLRequest, body: UploadEndpointBody) = try endpoint.makeRequest()
request.request = try requestAdapter.adapt(request.request)
Expand Down
36 changes: 36 additions & 0 deletions Tests/ApexyURLSessionTests/URLSessionClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,42 @@ final class URLSessionClientTests: XCTestCase {

wait(for: [exp], timeout: 0.1)
}

@available(iOS 13.0, *)
@available(macOS 10.15, *)
func testClientDataRequestUsingAsyncAwait() async throws {
let endpoint = EmptyEndpoint()
let data = "Test".data(using: .utf8)!
MockURLProtocol.requestHandler = { request in
let response = HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: "2.0", headerFields: nil)!
return (response, data)
}

do {
let content = try await client.request(endpoint)
XCTAssertEqual(content, data)
} catch {
XCTFail("Expected result: .success, actual result: .failure")
}
}

@available(iOS 13.0, *)
@available(macOS 10.15, *)
func testClientUploadUsingAsyncAwait() async throws {
let data = "apple".data(using: .utf8)!
let endpoint = SimpleUploadEndpoint(data: data)
MockURLProtocol.requestHandler = { request in
let response = HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: "2.0", headerFields: nil)!
return (response, data)
}

do {
let content = try await client.upload(endpoint)
XCTAssertEqual(content, data)
} catch {
XCTFail("Expected result: .success, actual result: .failure")
}
}
}

private final class MockURLProtocol: URLProtocol {
Expand Down