Xcode提示:Making a purchase without listening for transaction updates risks missing successful purchases. Create a Task to iterate Transaction.updates at launch.
Xcode提示:Making a purchase without listening for transaction updates risks missing successful purchases. Create a Task to iterate Transaction.updates at launch.

Xcode提示:Making a purchase without listening for transaction updates risks missing successful purchases. Create a Task to iterate Transaction.updates at launch.

问题描述

在配置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 对象,开发者可以通过它来处理这些交易。

完成截图

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注