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

iOS StoreKit 2:家庭共享组内设备如何接收待处理购买通知?

跨设备同步待处理购买状态(StoreKit 2 + 家庭共享场景)

核心问题原因

StoreKit 2的Transaction.updates和SubscriptionStatus.updates监听器仅在发起购买的设备上触发待处理状态通知,跨设备的家庭共享场景下,未发起购买的设备无法通过StoreKit原生API获取待处理购买的实时状态。


解决方案:iCloud Key-Value Storage 同步状态

利用家庭共享组内设备可共享访问的iCloud键值存储,手动同步待处理购买标记,实现多设备统一禁用付费墙。

1. 配置iCloud能力

  • 在Xcode项目的「Signing & Capabilities」中添加「iCloud」能力
  • 勾选「Key-Value Storage」,并创建/选择共享容器(容器ID需在开发者后台开启家庭共享权限)

2. 设备A:发起购买时写入待处理标记

在调用Product.purchase()前,立即写入iCloud KV存储标记,告知其他设备当前有未完成购买:

import Foundation

// 替换为你的iCloud容器ID
private let sharedSuiteID = "iCloud.com.yourcompany.yourapp"

func initiatePurchase(for product: Product) async {
    // 先标记待处理状态
    let sharedDefaults = UserDefaults(suiteName: sharedSuiteID)!
    sharedDefaults.set(true, forKey: "hasPendingPurchase")
    sharedDefaults.synchronize()
    
    // 发起购买
    do {
        let result = try await product.purchase()
        switch result {
        case .success(let verification):
            // 处理验证逻辑...
            // 交易完成后清除标记
            clearPendingPurchaseFlag()
        case .userCancelled, .pending:
            // 用户取消或仍在待处理,根据情况处理
            if case .userCancelled = result {
                clearPendingPurchaseFlag()
            }
        default:
            clearPendingPurchaseFlag()
        }
    } catch {
        print("购买失败: \(error)")
        clearPendingPurchaseFlag()
    }
}

private func clearPendingPurchaseFlag() {
    let sharedDefaults = UserDefaults(suiteName: sharedSuiteID)!
    sharedDefaults.removeObject(forKey: "hasPendingPurchase")
    sharedDefaults.synchronize()
}

3. 所有设备:监听KV存储变化并更新付费墙

在应用启动时添加监听器,实时同步待处理状态:

func setupPendingPurchaseListener() {
    let sharedDefaults = UserDefaults(suiteName: sharedSuiteID)!
    // 启动时先检查一次当前状态
    updatePaywallStatus(hasPending: sharedDefaults.bool(forKey: "hasPendingPurchase"))
    
    // 监听KV存储变化
    NotificationCenter.default.addObserver(
        self,
        selector: #selector(handleSharedDefaultsChange),
        name: UserDefaults.didChangeNotification,
        object: sharedDefaults
    )
}

@objc private func handleSharedDefaultsChange() {
    let sharedDefaults = UserDefaults(suiteName: sharedSuiteID)!
    let hasPending = sharedDefaults.bool(forKey: "hasPendingPurchase")
    updatePaywallStatus(hasPending: hasPending)
}

// 根据待处理状态更新付费墙(禁用/启用)
private func updatePaywallStatus(hasPending: Bool) {
    paywallView.isUserInteractionEnabled = !hasPending // 禁用付费墙交互
    purchaseButton.isEnabled = !hasPending
    pendingIndicator.isHidden = !hasPending // 显示"处理中"提示
}

兜底与边缘场景处理

  1. 离线设备同步:设备离线时KV存储变化不会实时推送,应用每次启动时主动检查KV存储状态即可
  2. 未登录iCloud的设备:此类设备无法共享KV存储,可在启动时提示用户登录iCloud以获得跨设备同步体验;同时依赖本地StoreKit查询确保已购权限不会被误拦截
  3. 多类型购买区分:若应用有多种付费产品(订阅/终身权限),可将标记改为具体产品ID(如键pendingProductID,值为产品ID),实现精准禁用对应付费选项

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 13:27:40