问题描述
在配置StoreKit 2的过程中,购买商品的方法代码行报错:
func purchaseProduct(_ product: Product) async throws -> Product.PurchaseResult {
let result = try await product.purchase() // 报错行
...
}
报错代码为:
Making a purchase without listening for transaction updates risks missing successful purchases. Create a Task to iterate Transaction.updates at launch.
该提示是关于应用内购买 (IAP) 的警告信息,表明在应用启动时没有监听 Transaction.updates,可能会导致错过用户在后台成功完成的购买。为了确保不会漏掉任何交易,应该在应用启动时设置一个 Task 来监听 Transaction.updates。
背景
在 iOS 应用中,如果用户在 App Store 完成购买后应用未能立即收到交易更新,可能是因为应用不在前台或者未监听交易更新。这就可能导致用户的购买没有被正确处理。因此,Apple 建议开发者在应用启动时监听 Transaction.updates 以接收并处理任何未完成的交易。
解决方法
在你的 IAPManager 或应用启动逻辑中,可以这样设置一个 Task 来监听 Transaction.updates。
参考代码:
import StoreKit
func startObservingTransactions() {
Task {
// 开始迭代监听 transaction 更新
for await transaction in Transaction.updates {
// 检查交易状态
await handle(transaction)
}
}
}
func handle(_ transaction: Transaction) async {
switch transaction {
case .verified(let verifiedTransaction):
// 处理经过验证的交易
await finishTransaction(verifiedTransaction)
case .unverified(_, let error):
// 处理交易失败或未验证的错误
print("Transaction failed with error: \(error.localizedDescription)")
}
}
func finishTransaction(_ transaction: Transaction) async {
// 完成购买处理,如解锁功能或提供内容
await transaction.finish()
}
在类中创建一个初始化方法,设置Task监听Transaction.updates
Task: 创建一个异步任务来监听 Transaction.updates。
for await: 使用 for await 来迭代 Transaction.updates,这是一个异步序列,表示从 App Store 收到的交易更新。
handle(transaction): 对每个交易执行处理逻辑,包括验证和完成购买。
transaction.finish(): 确保完成交易后调用 .finish(),否则会再次收到该交易的更新。
下面是我的实际代码:
@main
struct ERdepotApp: App {
@StateObject var iapManager = IAPManager.shared
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(iapManager)
.onAppear {
Task {
await iapManager.handleTransactions()
}
}
}
}
}
class IAPManager:ObservableObject {
static let shared = IAPManager()
private init() { }
// handleTransactions处理交易
func handleTransactions() async {
for await result in Transaction.updates {
do {
// 验证购买结果
let transaction = try checkVerified(result)
// 处理交易,例如解锁内容
savePurchasedState(for: transaction.productID)
await transaction.finish()
} catch {
print("交易处理失败:\(error)")
}
}
}
}
在应用启动时调用 handleTransactions,确保它在后台持续监听交易更新。可以在 App 的初始化方法或者 onAppear 中启动。
通过这种方式,handleTransactions 会在应用运行期间持续监听并处理任何交易更新。
Transaction.updates
Transaction.updates 是来自 StoreKit 框架的一个异步序列,它提供对应用程序内购的交易更新通知。在 iOS 的应用内购买 (In-App Purchase, IAP) 中,Transaction.updates 可以监听与交易相关的事件,例如新的购买、恢复购买和自动续订等。
当用户进行购买操作或 Apple 服务器有任何购买状态的更新时,Transaction.updates 会发送一个 Transaction 对象,开发者可以通过它来处理这些交易。