Skip to content

Replace withCheckedThrowingContinuation Calls With withUnsafeThrowingContinuation #4286

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

Merged
merged 4 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Sources/FoundationExtensions/AsyncExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ internal enum Async {
static func call<Value, Error: Swift.Error>(
method: (@escaping @Sendable (Result<Value, Error>) -> Void) -> Void
) async throws -> Value {
return try await withCheckedThrowingContinuation { continuation in
return try await withUnsafeThrowingContinuation { continuation in
Copy link
Member

Choose a reason for hiding this comment

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

let’s add a comment pointing to the issue for future reference

@Sendable
func complete(_ result: Result<Value, Error>) {
continuation.resume(with: result)
Expand All @@ -101,7 +101,10 @@ internal enum Async {
static func call<Value>(
method: (@escaping @Sendable (Value) -> Void) -> Void
) async -> Value {
return await withCheckedContinuation { continuation in
// Note: We're using UnsafeContinuation instead of Checked because
// of a crash in iOS 18.0 devices when CheckedContinuations are used.
// See: https://github.com/RevenueCat/purchases-ios/issues/4177
return await withUnsafeContinuation { continuation in
@Sendable
func complete(_ value: Value) {
continuation.resume(with: .success(value))
Expand Down
36 changes: 20 additions & 16 deletions Sources/Misc/Concurrency/Purchases+async.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,14 @@ import Foundation
/// This extension holds the biolerplate logic to convert methods with completion blocks into async / await syntax.
extension Purchases {

// Note: We're using UnsafeContinuation instead of Checked because
// of a crash in iOS 18.0 devices when CheckedContinuations are used.
// See: https://github.com/RevenueCat/purchases-ios/issues/4177

#if !ENABLE_CUSTOM_ENTITLEMENT_COMPUTATION

func logInAsync(_ appUserID: String) async throws -> (customerInfo: CustomerInfo, created: Bool) {
return try await withCheckedThrowingContinuation { continuation in
return try await withUnsafeThrowingContinuation { continuation in
logIn(appUserID) { customerInfo, created, error in
continuation.resume(with: Result(customerInfo, error)
.map { ($0, created) })
Expand All @@ -28,15 +32,15 @@ extension Purchases {
}

func logOutAsync() async throws -> CustomerInfo {
return try await withCheckedThrowingContinuation { continuation in
return try await withUnsafeThrowingContinuation { continuation in
logOut { customerInfo, error in
continuation.resume(with: Result(customerInfo, error))
}
}
}

func syncAttributesAndOfferingsIfNeededAsync() async throws -> Offerings? {
return try await withCheckedThrowingContinuation { continuation in
return try await withUnsafeThrowingContinuation { continuation in
syncAttributesAndOfferingsIfNeeded { offerings, error in
continuation.resume(with: Result(offerings, error))
}
Expand All @@ -46,23 +50,23 @@ extension Purchases {
#endif

func offeringsAsync(fetchPolicy: OfferingsManager.FetchPolicy) async throws -> Offerings {
return try await withCheckedThrowingContinuation { continuation in
return try await withUnsafeThrowingContinuation { continuation in
self.getOfferings(fetchPolicy: fetchPolicy) { offerings, error in
continuation.resume(with: Result(offerings, error))
}
}
}

func productsAsync(_ productIdentifiers: [String]) async -> [StoreProduct] {
return await withCheckedContinuation { continuation in
return await withUnsafeContinuation { continuation in
getProducts(productIdentifiers) { result in
continuation.resume(returning: result)
}
}
}

func purchaseAsync(product: StoreProduct) async throws -> PurchaseResultData {
return try await withCheckedThrowingContinuation { continuation in
return try await withUnsafeThrowingContinuation { continuation in
purchase(product: product) { transaction, customerInfo, error, userCancelled in
continuation.resume(with: Result(customerInfo, error)
.map { PurchaseResultData(transaction, $0, userCancelled) })
Expand All @@ -71,7 +75,7 @@ extension Purchases {
}

func purchaseAsync(package: Package) async throws -> PurchaseResultData {
return try await withCheckedThrowingContinuation { continuation in
return try await withUnsafeThrowingContinuation { continuation in
purchase(package: package) { transaction, customerInfo, error, userCancelled in
continuation.resume(with: Result(customerInfo, error)
.map { PurchaseResultData(transaction, $0, userCancelled) })
Expand All @@ -80,7 +84,7 @@ extension Purchases {
}

func restorePurchasesAsync() async throws -> CustomerInfo {
return try await withCheckedThrowingContinuation { continuation in
return try await withUnsafeThrowingContinuation { continuation in
self.restorePurchases { customerInfo, error in
continuation.resume(with: Result(customerInfo, error))
}
Expand All @@ -90,15 +94,15 @@ extension Purchases {
#if !ENABLE_CUSTOM_ENTITLEMENT_COMPUTATION

func syncPurchasesAsync() async throws -> CustomerInfo {
return try await withCheckedThrowingContinuation { continuation in
return try await withUnsafeThrowingContinuation { continuation in
syncPurchases { customerInfo, error in
continuation.resume(with: Result(customerInfo, error))
}
}
}

func purchaseAsync(product: StoreProduct, promotionalOffer: PromotionalOffer) async throws -> PurchaseResultData {
return try await withCheckedThrowingContinuation { continuation in
return try await withUnsafeThrowingContinuation { continuation in
purchase(product: product,
promotionalOffer: promotionalOffer) { transaction, customerInfo, error, userCancelled in
continuation.resume(with: Result(customerInfo, error)
Expand All @@ -108,7 +112,7 @@ extension Purchases {
}

func purchaseAsync(package: Package, promotionalOffer: PromotionalOffer) async throws -> PurchaseResultData {
return try await withCheckedThrowingContinuation { continuation in
return try await withUnsafeThrowingContinuation { continuation in
purchase(package: package,
promotionalOffer: promotionalOffer) { transaction, customerInfo, error, userCancelled in
continuation.resume(with: Result(customerInfo, error)
Expand All @@ -118,7 +122,7 @@ extension Purchases {
}

func customerInfoAsync(fetchPolicy: CacheFetchPolicy) async throws -> CustomerInfo {
return try await withCheckedThrowingContinuation { continuation in
return try await withUnsafeThrowingContinuation { continuation in
getCustomerInfo(fetchPolicy: fetchPolicy) { customerInfo, error in
continuation.resume(with: Result(customerInfo, error))
}
Expand All @@ -127,7 +131,7 @@ extension Purchases {

func checkTrialOrIntroductoryDiscountEligibilityAsync(_ product: StoreProduct) async
-> IntroEligibilityStatus {
return await withCheckedContinuation { continuation in
return await withUnsafeContinuation { continuation in
checkTrialOrIntroDiscountEligibility(product: product) { status in
continuation.resume(returning: status)
}
Expand All @@ -136,7 +140,7 @@ extension Purchases {

func checkTrialOrIntroductoryDiscountEligibilityAsync(_ productIdentifiers: [String]) async
-> [String: IntroEligibility] {
return await withCheckedContinuation { continuation in
return await withUnsafeContinuation { continuation in
checkTrialOrIntroDiscountEligibility(productIdentifiers: productIdentifiers) { result in
continuation.resume(returning: result)
}
Expand All @@ -145,7 +149,7 @@ extension Purchases {

func promotionalOfferAsync(forProductDiscount discount: StoreProductDiscount,
product: StoreProduct) async throws -> PromotionalOffer {
return try await withCheckedThrowingContinuation { continuation in
return try await withUnsafeThrowingContinuation { continuation in
getPromotionalOffer(forProductDiscount: discount, product: product) { offer, error in
continuation.resume(with: Result(offer, error))
}
Expand Down Expand Up @@ -197,7 +201,7 @@ extension Purchases {
@available(watchOS, unavailable)
@available(tvOS, unavailable)
func showManageSubscriptionsAsync() async throws {
return try await withCheckedThrowingContinuation { continuation in
return try await withUnsafeThrowingContinuation { continuation in
showManageSubscriptions { error in
if let error = error {
continuation.resume(throwing: error)
Expand Down
10 changes: 8 additions & 2 deletions Sources/Purchasing/ReceiptFetcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,10 @@ class ReceiptFetcher {
}

func receiptData(refreshPolicy: ReceiptRefreshPolicy) async -> Data? {
return await withCheckedContinuation { continuation in
// Note: We're using UnsafeContinuation instead of Checked because
// of a crash in iOS 18.0 devices when CheckedContinuations are used.
// See: https://github.com/RevenueCat/purchases-ios/issues/4177
return await withUnsafeContinuation { continuation in
self.receiptData(refreshPolicy: refreshPolicy) { result, _ in
continuation.resume(returning: result)
}
Expand Down Expand Up @@ -155,7 +158,10 @@ private extension ReceiptFetcher {

/// `async` version of `refreshReceipt(_:)`
func refreshReceipt() async -> (Data, URL?) {
await withCheckedContinuation { continuation in
// Note: We're using UnsafeContinuation instead of Checked because
// of a crash in iOS 18.0 devices when CheckedContinuations are used.
// See: https://github.com/RevenueCat/purchases-ios/issues/4177
await withUnsafeContinuation { continuation in
self.refreshReceipt {
continuation.resume(returning: ($0, $1))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ final class ExternalPurchasesManager: NSObject {
extension ExternalPurchasesManager {

func purchase(sk1Product product: SK1Product) async throws -> SK1PurchaseCompletedResult {
return try await withCheckedThrowingContinuation { continuation in
return try await withUnsafeThrowingContinuation { continuation in
self.purchase(sk1Product: product) { transaction in
if let error = transaction.error {
continuation.resume(throwing: error)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ final class SK1ProductFetcher: NSObject {
}

func products(with identifiers: Set<String>) async throws -> Set<SK1Product> {
return try await withCheckedThrowingContinuation { continuation in
return try await withUnsafeThrowingContinuation { continuation in
self.products(with: identifiers) { result in
continuation.resume(with: result)
}
Expand Down
5 changes: 4 additions & 1 deletion Tests/RevenueCatUITests/ImageLoaderTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,10 @@ private final class MockAsyncURLSession: NSObject, URLSessionType {
self.completionSet = false
self.completion = nil

return try await withCheckedContinuation { continuation in
// Note: We're using UnsafeContinuation instead of Checked because
// of a crash in iOS 18.0 devices when CheckedContinuations are used.
// See: https://github.com/RevenueCat/purchases-ios/issues/4177
return try await withUnsafeContinuation { continuation in
self.completion = { value in
continuation.resume(returning: value)
}
Expand Down
7 changes: 5 additions & 2 deletions Tests/RevenueCatUITests/Purchasing/PurchaseHandlerTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,10 @@ class PurchaseHandlerTests: TestCase {
@available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *)
private final class AsyncPurchaseHandler {

var continuation: CheckedContinuation<Void, Never>?
// Note: We're using UnsafeContinuation instead of Checked because
// of a crash in iOS 18.0 devices when CheckedContinuations are used.
// See: https://github.com/RevenueCat/purchases-ios/issues/4177
var continuation: UnsafeContinuation<Void, Never>?
private(set) var purchaseHandler: PurchaseHandler!

init() {
Expand Down Expand Up @@ -260,7 +263,7 @@ private final class AsyncPurchaseHandler {
}

private func createAndWaitForContinuation() async {
await withCheckedContinuation { [weak self] continuation in
await withUnsafeContinuation { [weak self] continuation in
self?.continuation = continuation
}
}
Expand Down
4 changes: 2 additions & 2 deletions Tests/StoreKitUnitTests/PurchasesOrchestratorSK1Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ class PurchasesOrchestratorSK1Tests: BasePurchasesOrchestratorTests, PurchasesOr
payment.productIdentifier = ""

let (transaction, customerInfo, error, cancelled) =
try await withCheckedThrowingContinuation { continuation in
try await withUnsafeThrowingContinuation { continuation in
self.orchestrator.purchase(
sk1Product: product,
payment: payment,
Expand All @@ -287,7 +287,7 @@ class PurchasesOrchestratorSK1Tests: BasePurchasesOrchestratorTests, PurchasesOr
let payment = self.storeKit1Wrapper.payment(with: product)
self.receiptFetcher.shouldReturnReceipt = false

let (_, _, error, _) = try await withCheckedThrowingContinuation { continuation in
let (_, _, error, _) = try await withUnsafeThrowingContinuation { continuation in
self.orchestrator.purchase(
sk1Product: product,
payment: payment,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ final class ProductFetcherSK1: NSObject {
}

func products(with identifiers: Set<String>) async throws -> Set<SK1Product> {
return try await withCheckedThrowingContinuation { continuation in
return try await withUnsafeThrowingContinuation { continuation in
self.products(with: identifiers) { result in
continuation.resume(with: result)
}
Expand Down