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

如何在StoreKit中通过产品ID/displayName获取产品实现独立购买按钮

按产品ID绑定StoreKit购买按钮的解决方案

核心思路是不要依赖products数组的元素顺序,而是通过产品唯一ID(product.id)精准定位对应的Product对象,这样无论数组顺序如何变化,都能匹配到正确的产品。

1. 先定义产品ID常量

把你需要的3个产品ID定义成常量,避免拼写错误且方便复用:

// 替换成你实际的App Store Connect配置的产品ID
let premiumProductID = "com.yourapp.premium"
let monthlySubscriptionID = "com.yourapp.sub.monthly"
let yearlySubscriptionID = "com.yourapp.sub.yearly"

2. 通过ID精准查找产品

使用first(where:)方法根据ID匹配产品,代替依赖数组的first/last,同时用可选绑定避免强制解包:

// 示例:第一个产品按钮
if let premiumProduct = products.first(where: { $0.id == premiumProductID }) {
    Button {
        Task {
            do {
                let transaction = try await purchaseProduct(premiumProduct)
                // 在这里处理购买成功后的逻辑,比如解锁高级功能
            } catch PurchaseError.pending {
                // 处理付款待确认的情况
            } catch PurchaseError.cancelled {
                // 用户取消购买
            } catch PurchaseError.failed {
                // 购买失败,提示用户
            } catch {
                // 捕获其他未知错误
            }
        }
    } label: {
        HStack {
            Text(premiumProduct.displayName)
            Spacer()
            Text(premiumProduct.displayPrice)
        }
    }
} else {
    // 产品未加载到的降级处理:显示占位按钮并禁用
    Button(action: {}, label: {
        HStack {
            Text("产品加载中")
            Spacer()
            Text("--")
        }
    })
    .disabled(true)
    .opacity(0.6)
}

3. 复用逻辑实现另外两个按钮

按照同样的方式,给另外两个按钮绑定对应的产品ID即可:

// 第二个产品按钮(月度订阅)
if let monthlySub = products.first(where: { $0.id == monthlySubscriptionID }) {
    Button {
        Task {
            do {
                try await purchaseProduct(monthlySub)
                // 处理订阅逻辑
            } catch {
                // 错误处理
            }
        }
    } label: {
        HStack {
            Text(monthlySub.displayName)
            Spacer()
            Text(monthlySub.displayPrice)
        }
    }
} else {
    // 降级UI
    Button(action: {}, label: {
        HStack {
            Text("产品加载中")
            Spacer()
            Text("--")
        }
    })
    .disabled(true)
    .opacity(0.6)
}

// 第三个产品按钮(年度订阅)
// 代码结构和上面完全一致,替换对应的产品ID即可

可选优化:给[Product]添加扩展

如果多处需要按ID查找产品,可以给[Product]添加扩展简化调用:

extension Array where Element == Product {
    func product(withID id: String) -> Product? {
        first(where: { $0.id == id })
    }
}

之后调用就更简洁:

if let yearlySub = products.product(withID: yearlySubscriptionID) {
    // 按钮逻辑
}

这种方式的优势

  • 彻底避免强制解包的风险,通过可选绑定安全处理产品未加载的情况
  • 不依赖数组顺序,产品列表顺序变化不会导致UI绑定错误
  • 代码可读性更强,直接对应具体产品ID,逻辑清晰

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 21:50:39