diff --git a/Package.swift b/Package.swift index f31b6a8..c17ad0c 100644 --- a/Package.swift +++ b/Package.swift @@ -1,12 +1,12 @@ -// swift-tools-version:5.3 +// swift-tools-version:5.6 import PackageDescription let package = Package( name: "SwiftyAPNS", platforms: [ - .iOS(.v12), - .macOS(.v10_13) + .iOS(.v13), + .macOS(.v12) ], products: [ .library( diff --git a/README.md b/README.md index 12259a8..aea6304 100644 --- a/README.md +++ b/README.md @@ -44,18 +44,12 @@ let notification = APNSNotification.init(payload: <#Notification Payload#>, The values in responses can be handled asynchronously. ```swift -provider.push(notification) { (result) in - switch(result) { - case .success(let responce): - if let error = responce.reason { - // Push Notification failure - } else { - // Push Notification was successfully sent - } - case .failure(let error): + do { + let responce = try await provider.push(notification) + // Push Notification was successfully sent + } catch { // Push Notification failure } -} ``` ### [More examples](/Tests/SwiftyAPNSTests/SwiftyAPNSTests.swift) diff --git a/Sources/SwiftyAPNS/Provider/CertificateProvider.swift b/Sources/SwiftyAPNS/Provider/CertificateProvider.swift index 420e87d..7b446e5 100644 --- a/Sources/SwiftyAPNS/Provider/CertificateProvider.swift +++ b/Sources/SwiftyAPNS/Provider/CertificateProvider.swift @@ -11,39 +11,26 @@ import Foundation internal final class APNSCertificateProvider: NSObject, APNSSendMessageProtocol { private var identity: SecIdentity - private var sesion: URLSession = URLSession.shared + private var session: URLSession = URLSession.shared private static let decoder = JSONDecoder() - public init(identity: SecIdentity, sandbox: Bool = true, configuration: URLSessionConfiguration = URLSessionConfiguration.default, qeue: OperationQueue = OperationQueue.main) { + public init(identity: SecIdentity, sandbox: Bool = true, configuration: URLSessionConfiguration = URLSessionConfiguration.default) { self.identity = identity super.init() - self.sesion = URLSession.init(configuration: configuration, delegate: self, delegateQueue: qeue) + self.session = URLSession.init(configuration: configuration, delegate: self, delegateQueue: nil) } - public func push(_ notification: APNSNotification

, completion: @escaping (Result) -> Void) { - do { - let request = try APNSRequestFactory.makeRequest(notification) - let task = self.sesion.dataTask(with: request) { (data, responce, error) in - if let error = error { - completion(.failure(error)) - } else if let responce = responce as? HTTPURLResponse, let data = data { - if let apnsStatus = APNSStatus(code: responce.statusCode), - let apnsId = responce.allHeaderFields["apns-id"] as? String - { - let reason = try? Self.decoder.decode(APNSError.self, from: data) - let apnsResponce = APNSResponse(status: apnsStatus, apnsId: apnsId, reason: reason) - completion(.success(apnsResponce)) - } else { - completion(.failure(APNSProviderError.parseResponce)) - } - } else { - completion(.failure(APNSProviderError.emptyData)) - } - } - task.resume() - } catch { - completion(.failure(error)) + public func push(_ notification: APNSNotification

) async throws -> APNSResponse { + let request = try APNSRequestFactory.makeRequest(notification) + let (data, response) = try await session.data(for: request) + if let responce = response as? HTTPURLResponse, + let apnsStatus = APNSStatus(code: responce.statusCode), + let apnsId = responce.allHeaderFields["apns-id"] as? String { + let reason = try? Self.decoder.decode(APNSError.self, from: data) + return APNSResponse(status: apnsStatus, apnsId: apnsId, reason: reason) + } else { + throw APNSProviderError.parseResponce } } } diff --git a/Sources/SwiftyAPNS/Provider/KeyProvider.swift b/Sources/SwiftyAPNS/Provider/KeyProvider.swift index ca96ce4..9490897 100644 --- a/Sources/SwiftyAPNS/Provider/KeyProvider.swift +++ b/Sources/SwiftyAPNS/Provider/KeyProvider.swift @@ -11,45 +11,30 @@ import Foundation internal final class APNSKeyProvider: APNSSendMessageProtocol { private let token: APNSBearerToken - private let sesion: URLSession + private let session: URLSession - private static let encoder = JSONEncoder() private static let decoder = JSONDecoder() public init(p8: P8, keyId: String, teamId: String, sandbox: Bool = true, - configuration: URLSessionConfiguration = URLSessionConfiguration.default, - qeue: OperationQueue = OperationQueue.main) + configuration: URLSessionConfiguration = URLSessionConfiguration.default) { self.token = APNSBearerToken(p8: p8, keyId: keyId, teamId: teamId) - self.sesion = URLSession.init(configuration: configuration, delegate: nil, delegateQueue: qeue) + self.session = URLSession.init(configuration: configuration) } - public func push(_ notification: APNSNotification

, completion: @escaping (Result) -> Void) { - do { - var request = try APNSRequestFactory.makeRequest(notification) - let dataToken = try token.generateIfExpired() - request.setValue("application/json;", forHTTPHeaderField: "Content-Type") - request.setValue("bearer \(dataToken)", forHTTPHeaderField: "Authorization") - let task = self.sesion.dataTask(with: request) { (data, responce, error) in - if let error = error { - completion(.failure(error)) - } else if let responce = responce as? HTTPURLResponse, let data = data { - if let apnsStatus = APNSStatus(code: responce.statusCode), - let apnsId = responce.allHeaderFields["apns-id"] as? String - { - let reason = try? Self.decoder.decode(APNSError.self, from: data) - let apnsResponce = APNSResponse(status: apnsStatus, apnsId: apnsId, reason: reason) - completion(.success(apnsResponce)) - } else { - completion(.failure(APNSProviderError.parseResponce)) - } - } else { - completion(.failure(APNSProviderError.emptyData)) - } - } - task.resume() - } catch { - completion(.failure(error)) + public func push(_ notification: APNSNotification

) async throws -> APNSResponse { + var request = try APNSRequestFactory.makeRequest(notification) + let dataToken = try token.generateIfExpired() + request.setValue("application/json;", forHTTPHeaderField: "Content-Type") + request.setValue("bearer \(dataToken)", forHTTPHeaderField: "Authorization") + let (data, response) = try await session.data(for: request) + if let responce = response as? HTTPURLResponse, + let apnsStatus = APNSStatus(code: responce.statusCode), + let apnsId = responce.allHeaderFields["apns-id"] as? String { + let reason = try? Self.decoder.decode(APNSError.self, from: data) + return APNSResponse(status: apnsStatus, apnsId: apnsId, reason: reason) + } else { + throw APNSProviderError.parseResponce } } } diff --git a/Sources/SwiftyAPNS/Provider/Provider.swift b/Sources/SwiftyAPNS/Provider/Provider.swift index f42867b..cb7cc70 100644 --- a/Sources/SwiftyAPNS/Provider/Provider.swift +++ b/Sources/SwiftyAPNS/Provider/Provider.swift @@ -11,23 +11,21 @@ import Foundation public struct APNSProvider { private let provider: APNSSendMessageProtocol - public func push(_ notification: APNSNotification

, completion: @escaping (Result) -> Void) { - self.provider.push(notification, completion: completion) + public func push(_ notification: APNSNotification

) async throws -> APNSResponse { + try await self.provider.push(notification) } } extension APNSProvider { public init(identity: SecIdentity, sandbox: Bool = true, - configuration: URLSessionConfiguration = URLSessionConfiguration.default, - qeue: OperationQueue = OperationQueue.main) + configuration: URLSessionConfiguration = URLSessionConfiguration.default) { - self.provider = APNSCertificateProvider(identity: identity, sandbox: sandbox, configuration: configuration, qeue: qeue) + self.provider = APNSCertificateProvider(identity: identity, sandbox: sandbox, configuration: configuration) } public init(p8: P8, keyId: String, teamId: String, sandbox: Bool = true, - configuration: URLSessionConfiguration = URLSessionConfiguration.default, - qeue: OperationQueue = OperationQueue.main) + configuration: URLSessionConfiguration = URLSessionConfiguration.default) { - self.provider = APNSKeyProvider(p8: p8, keyId: keyId, teamId: teamId, sandbox: sandbox, configuration: configuration, qeue: qeue) + self.provider = APNSKeyProvider(p8: p8, keyId: keyId, teamId: teamId, sandbox: sandbox, configuration: configuration) } } diff --git a/Sources/SwiftyAPNS/Provider/SendMessageProtocol.swift b/Sources/SwiftyAPNS/Provider/SendMessageProtocol.swift index d4477b9..e74b07d 100644 --- a/Sources/SwiftyAPNS/Provider/SendMessageProtocol.swift +++ b/Sources/SwiftyAPNS/Provider/SendMessageProtocol.swift @@ -7,5 +7,5 @@ // internal protocol APNSSendMessageProtocol { - func push(_ notification: APNSNotification

, completion: @escaping (Result) -> Void) + func push(_ notification: APNSNotification

) async throws -> APNSResponse } diff --git a/Tests/SwiftyAPNSTests/SwiftyAPNSTests+Private.swift b/Tests/SwiftyAPNSTests/SwiftyAPNSTests+Private.swift index c001de9..22c9c2e 100644 --- a/Tests/SwiftyAPNSTests/SwiftyAPNSTests+Private.swift +++ b/Tests/SwiftyAPNSTests/SwiftyAPNSTests+Private.swift @@ -7,47 +7,23 @@ import XCTest @testable import SwiftyAPNS extension SwiftyAPNSTests { - func sendPushNotification(_ notification: APNSNotification

) { + func sendPushNotification(_ notification: APNSNotification

) async throws { #if false let encoder = JSONEncoder() encoder.outputFormatting = .prettyPrinted let encoded = try! encoder.encode(notification.payload) print("Payload:\n\(String(data: encoded, encoding: .utf8)!)") #endif - let expect = self.expectation(description: "APNSExpectation") - provider.push(notification) { (result) in - switch(result) { - case .success(let responce): - if let error = responce.reason { - XCTFail(error.errorDescription ?? "Failure send push notification") - } else { - print("ApnsId: \(responce.apnsId)") - expect.fulfill() - } - case .failure(let error): - if let error = error as? LocalizedError { - XCTFail(error.localizedDescription) - } else { - XCTFail("Failure send push notification") - } - } - } - } - - func waitForResponce() { - self.waitForExpectations(timeout: 30.0) { (error) in - if let error = error { - XCTFail(error.localizedDescription) - } - } + let responce = try await provider.push(notification) + XCTAssertNil(responce.reason) } - func visit(notification: Notification) { + func visit(notification: Notification) async throws { switch notification { case .payload(let notificatiuon): - sendPushNotification(notificatiuon) + try await sendPushNotification(notificatiuon) case .payload4(let notificatiuon): - sendPushNotification(notificatiuon) + try await sendPushNotification(notificatiuon) } } diff --git a/Tests/SwiftyAPNSTests/SwiftyAPNSTests.swift b/Tests/SwiftyAPNSTests/SwiftyAPNSTests.swift index 89e5230..80cd171 100644 --- a/Tests/SwiftyAPNSTests/SwiftyAPNSTests.swift +++ b/Tests/SwiftyAPNSTests/SwiftyAPNSTests.swift @@ -116,47 +116,39 @@ final class SwiftyAPNSTests: XCTestCase { #endif } - func testAlertPushExample() { - sendPushNotification(alertPushExample) - waitForResponce() + func testAlertPushExample() async throws { + try await sendPushNotification(alertPushExample) } - func testAlertWithSubtitlePushExample() { - sendPushNotification(alertWithSubtitlePushExample) - waitForResponce() + func testAlertWithSubtitlePushExample() async throws { + try await sendPushNotification(alertWithSubtitlePushExample) } - func testLocalizableAlertPushExample() { - sendPushNotification(localizableAlertPushExample) - waitForResponce() + func testLocalizableAlertPushExample() async throws { + try await sendPushNotification(localizableAlertPushExample) } - func testAlertWithCustomActionsPushExample() { - sendPushNotification(alertWithCustomActionsPushExample) - waitForResponce() + func testAlertWithCustomActionsPushExample() async throws { + try await sendPushNotification(alertWithCustomActionsPushExample) } - func testLocalizableAlertPushWithCustomPayloadExample1() { - sendPushNotification(localizableAlertPushWithCustomPayloadExample1) - waitForResponce() + func testLocalizableAlertPushWithCustomPayloadExample1() async throws { + try await sendPushNotification(localizableAlertPushWithCustomPayloadExample1) } - func testLocalizableAlertPushWithCustomPayloadExample2() { - sendPushNotification(localizableAlertPushWithCustomPayloadExample2) - waitForResponce() + func testLocalizableAlertPushWithCustomPayloadExample2() async throws { + try await sendPushNotification(localizableAlertPushWithCustomPayloadExample2) } - func testModifyingContentPushExample() { - sendPushNotification(modifyingContentPushExample) - waitForResponce() + func testModifyingContentPushExample() async throws { + try await sendPushNotification(modifyingContentPushExample) } - func testBackgroundPushExample() { - sendPushNotification(backgroundPushExample) - waitForResponce() + func testBackgroundPushExample() async throws { + try await sendPushNotification(backgroundPushExample) } - func testSendingMultiplePushes() { + func testSendingMultiplePushes() async throws { let notifications: [Notification] = [ .payload(notificatiuon: alertPushExample), .payload(notificatiuon: alertWithSubtitlePushExample), @@ -164,8 +156,9 @@ final class SwiftyAPNSTests: XCTestCase { .payload(notificatiuon: alertWithCustomActionsPushExample), .payload4(notificatiuon: backgroundPushExample) ] - notifications.forEach(visit) - waitForResponce() + for notification in notifications { + try await visit(notification: notification) + } } static var allTests = [