You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

StoreKit 2内购产品错误报告模块无法识别StoreKitError求助

StoreKit 2 加载内购产品错误处理问题

我正在用StoreKit 2配置非消耗型内购产品,苹果在App Store Connect/Xcode的内购配置文档里建议提交审核前要测试43种错误场景,但不管是苹果官方还是其他在线示例,都没给出覆盖这些错误的代码实现。

目前我主要卡在**加载产品(load product)**相关的错误处理上。根据苹果对products(for:)方法的说明:

若存在无效标识符或App Store无法找到对应标识符,这些标识符会被排除在返回值外;products(for:)函数可能因系统相关错误抛出StoreKitError。

测试加载产品错误时,所有场景都只显示带加载轮(progressView())的空白页面,而且代码里的错误捕获switch语句还报错,比如**"Type '[Product]' has no member 'systemError'"**,看起来代码识别不了我自定义的StoreKitError枚举。

以下是StoreModel的部分代码:

@MainActor final class StoreModel: ObservableObject {

enum StoreKitError {
        case networkError(URLError)
        case systemError(any Error)
        case userCancelled
        case notAvailableInStorefront
        case notEntitled
        case unknown
    }

public enum PurchaseFinishedAction {
        case dismissStore
        case noAction
        case displayError
    }

  func fetchProducts() async throws -> PurchaseFinishedAction {
        let action: PurchaseFinishedAction
        do {
            products = try await Product.products(
                for: productIDs)
        } catch {
            
            switch products {
            case .networkError(URLError):
                action = .displayError
            case .systemError(any Error):
                action = .displayError
            case .userCancelled:
                action = .noAction
            case .notAvailableInStorefront:
                action = .displayError
            case .notEntitled:
                action = .displayError
            case .product.unknown:
                action = .displayError
            }
        }
        return action
    }
}

代码问题分析

  1. 错误分支里不该switch products:products是请求成功时才会赋值的数组,错误场景下它的类型是[Product],根本没有自定义枚举的case,这是报错的核心原因。
  2. 未处理系统错误映射:Product.products(for:)抛出的是系统自带的StoreKit.Error,不是自定义的StoreKitError枚举,需要手动做类型转换和映射。
  3. Switch case写法错误:比如.networkError(URLError)这种写法不符合Swift枚举匹配语法,应该用模式匹配绑定错误值。

修正后的代码示例

@MainActor final class StoreModel: ObservableObject {
    @Published var products: [Product] = []
    let productIDs: [String] = ["your.product.id1", "your.product.id2"]
    
    enum StoreKitError {
        case networkError(URLError)
        case systemError(any Error)
        case userCancelled
        case notAvailableInStorefront
        case notEntitled
        case invalidProductIDs
        case unknown
    }

    public enum PurchaseFinishedAction {
        case dismissStore
        case noAction
        case displayError
    }

    func fetchProducts() async -> PurchaseFinishedAction {
        let action: PurchaseFinishedAction
        do {
            products = try await Product.products(for: productIDs)
            // 处理无效产品ID场景:返回产品数量少于请求ID数量
            if products.count != productIDs.count {
                action = .displayError
            } else {
                action = .noAction
            }
        } catch {
            let customError = mapToCustomError(error)
            switch customError {
            case .networkError, .systemError, .notAvailableInStorefront, .notEntitled, .invalidProductIDs, .unknown:
                action = .displayError
            case .userCancelled:
                action = .noAction
            }
        }
        return action
    }
    
    // 系统错误转自定义错误的映射方法
    private func mapToCustomError(_ error: Error) -> StoreKitError {
        guard let storeKitError = error as? StoreKit.Error else {
            return .systemError(error)
        }
        
        switch storeKitError {
        case .networkError(let urlError):
            return .networkError(urlError)
        case .userCancelled:
            return .userCancelled
        case .notAvailableInStorefront:
            return .notAvailableInStorefront
        case .notEntitled:
            return .notEntitled
        default:
            return .unknown
        }
    }
}

关键补充说明

  1. 无效ID单独处理:products(for:)不会为无效ID抛出错误,只会过滤掉这些ID,所以需要对比请求ID数量和返回产品数量来识别该场景。
  2. 加载状态控制:在View层要结合products的空状态、fetchProducts的返回action来管理加载轮显示,比如请求开始时显示加载轮,结束后隐藏,失败时展示错误提示。
  3. 错误场景测试:可以用Xcode的StoreKit测试工具或Sandbox环境模拟错误,比如断网测试网络错误、用未配置的ID测试无效ID场景等。

内容的提问来源于stack exchange,提问作者Galen Smith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 05:43:36