From f094c2004c91843c21efa6b1d9c2fd015f73baea Mon Sep 17 00:00:00 2001 From: Hyo Date: Wed, 11 Feb 2026 11:54:32 +0900 Subject: [PATCH 1/2] chore(ios): fix Swift 6 warnings and deprecated API usage - Add explicit @unchecked Sendable conformance to OpenIapException - Capture products as local constant before MainActor.run closure - Add _ = to suppress unused result warning for finishTransaction Closes #3146 Co-Authored-By: Claude Opus 4.5 --- ios/HybridRnIap.swift | 6 ++++-- ios/RnIapHelper.swift | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ios/HybridRnIap.swift b/ios/HybridRnIap.swift index 12f154304..f225b83ce 100644 --- a/ios/HybridRnIap.swift +++ b/ios/HybridRnIap.swift @@ -132,8 +132,10 @@ class HybridRnIap: HybridRnIapSpec { products.append(product) seenIds.insert(product.id) } + // Capture products as local constant to avoid Swift 6 concurrency warning + let capturedProducts = products await MainActor.run { - products.forEach { self.productTypeBySku[$0.id] = $0.type.lowercased() } + capturedProducts.forEach { self.productTypeBySku[$0.id] = $0.type.lowercased() } } RnIapLog.result( "fetchProducts", products.map { ["id": $0.id, "type": $0.type] } @@ -327,7 +329,7 @@ class HybridRnIap: HybridRnIapSpec { let sanitizedPayload = RnIapHelper.sanitizeDictionary(purchasePayload) RnIapLog.payload("finishTransaction.nativePayload", sanitizedPayload) let purchaseInput = try OpenIapSerialization.purchaseInput(from: purchasePayload) - try await OpenIapModule.shared.finishTransaction(purchase: purchaseInput, isConsumable: nil) + _ = try await OpenIapModule.shared.finishTransaction(purchase: purchaseInput, isConsumable: nil) RnIapLog.result("finishTransaction", true) await MainActor.run { self.purchasePayloadById.removeValue(forKey: iosParams.transactionId) diff --git a/ios/RnIapHelper.swift b/ios/RnIapHelper.swift index 6f6eef7fc..32cb7f29f 100644 --- a/ios/RnIapHelper.swift +++ b/ios/RnIapHelper.swift @@ -5,7 +5,7 @@ import OpenIAP /// Similar to Android's OpenIapException, this wraps errors with JSON-serialized messages. /// Uses NSError for better compatibility with Objective-C bridging in Nitro. @available(iOS 15.0, *) -class OpenIapException: NSError { +class OpenIapException: NSError, @unchecked Sendable { static let domain = "com.margelo.nitro.rniap" convenience init(_ json: String) { From 4b50781485227afe97e916ad0cc254080bdd35ef Mon Sep 17 00:00:00 2001 From: Hyo Date: Wed, 11 Feb 2026 14:57:13 +0900 Subject: [PATCH 2/2] refactor(ios): use capture list for Swift 6 concurrency Use idiomatic Swift capture list [products] instead of creating a separate local constant for cleaner, more concise code. Co-Authored-By: Claude Opus 4.5 --- ios/HybridRnIap.swift | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ios/HybridRnIap.swift b/ios/HybridRnIap.swift index f225b83ce..7c8dc6a4a 100644 --- a/ios/HybridRnIap.swift +++ b/ios/HybridRnIap.swift @@ -132,10 +132,8 @@ class HybridRnIap: HybridRnIapSpec { products.append(product) seenIds.insert(product.id) } - // Capture products as local constant to avoid Swift 6 concurrency warning - let capturedProducts = products - await MainActor.run { - capturedProducts.forEach { self.productTypeBySku[$0.id] = $0.type.lowercased() } + await MainActor.run { [products] in + products.forEach { self.productTypeBySku[$0.id] = $0.type.lowercased() } } RnIapLog.result( "fetchProducts", products.map { ["id": $0.id, "type": $0.type] }