Swift集成Superwall与RevenueCat:订阅状态判断异常问题
Swift集成Superwall与RevenueCat:付费墙仅对未订阅用户展示的问题
我在Swift项目中集成Superwall和RevenueCat,因Superwall配置便捷选择了该工具,但目前无法实现仅向未订阅用户展示付费墙的逻辑。在PaywallDelegate扩展的isUserSubscribed方法中判断用户订阅状态时,首次运行始终返回false,导致用户一直看到付费墙,寻求解决方法。
相关代码
extension PaywallService: PaywallDelegate { // 1 处理购买逻辑 func purchase(product: SKProduct) { Task { do { let result = try await Purchases.shared.purchase(product: StoreProduct(sk1Product: product)) // 处理购买结果 print(result) } catch { // 处理购买错误 } } } // 2 恢复购买 func restorePurchases(completion: @escaping (Bool) -> Void) { Task { do { let purchaserInfo = try await Purchases.shared.restorePurchases() // 检查"subPlan"权益是否激活 let restored = purchaserInfo.entitlements.all["subPlan"]?.isActive == true completion(restored) } catch { completion(false) } } } // 3 判断用户是否订阅(问题所在) func isUserSubscribed() -> Bool { // 问题:首次运行始终返回false,用户一直看到付费墙 var isSub: Bool = false Purchases.shared.getCustomerInfo { purchaserInfo, error in // 异步获取用户订阅信息 isSub = purchaserInfo?.entitlements.all["subPlan"]?.isActive == true } return isSub } }
问题根源
isUserSubscribed是同步方法,但你在里面调用了RevenueCat的异步方法getCustomerInfo。方法执行时会直接返回初始值false,此时异步回调还没完成,订阅状态的更新根本没生效,所以首次运行必然返回false。
解决方法
1. 缓存订阅状态,避免异步回调延迟
在PaywallService中维护一个缓存变量存储订阅状态,提前预加载并在状态变化时更新:
步骤1:添加缓存变量
class PaywallService { // 缓存订阅状态,默认未订阅 private var cachedIsSubscribed: Bool = false // 其他属性... }
步骤2:预加载订阅状态
在App启动或PaywallService初始化时,异步加载用户订阅状态并更新缓存:
func loadSubscriptionStatus() async { do { let purchaserInfo = try await Purchases.shared.customerInfo() cachedIsSubscribed = purchaserInfo.entitlements.all["subPlan"]?.isActive == true } catch { cachedIsSubscribed = false } }
步骤3:修改isUserSubscribed方法
直接返回缓存的状态,避免异步等待:
func isUserSubscribed() -> Bool { return cachedIsSubscribed }
步骤4:订阅状态变化时更新缓存
- 购买成功后更新:
func purchase(product: SKProduct) { Task { do { let result = try await Purchases.shared.purchase(product: StoreProduct(sk1Product: product)) // 购买成功后更新缓存 if let purchaserInfo = result.customerInfo { cachedIsSubscribed = purchaserInfo.entitlements.all["subPlan"]?.isActive == true } } catch { // 处理错误 } } }
- 恢复购买后更新:
func restorePurchases(completion: @escaping (Bool) -> Void) { Task { do { let purchaserInfo = try await Purchases.shared.restorePurchases() let restored = purchaserInfo.entitlements.all["subPlan"]?.isActive == true cachedIsSubscribed = restored completion(restored) } catch { cachedIsSubscribed = false completion(false) } } }
- 监听RevenueCat的状态更新通知,实时同步:
// 在PaywallService初始化时添加监听 NotificationCenter.default.addObserver(forName: .PurchasesCustomerInfoUpdated, object: nil, queue: .main) { [weak self] notification in guard let purchaserInfo = notification.object as? PurchaserInfo else { return } self?.cachedIsSubscribed = purchaserInfo.entitlements.all["subPlan"]?.isActive == true }
2. 异步触发付费墙(替代方案)
如果Superwall允许,也可以在触发付费墙前先异步确认订阅状态,再决定是否展示:
func showPaywallIfNeeded() async { do { let purchaserInfo = try await Purchases.shared.customerInfo() let isSubscribed = purchaserInfo.entitlements.all["subPlan"]?.isActive == true if !isSubscribed { // 仅向未订阅用户展示付费墙 Superwall.shared.showPaywall() } } catch { // 网络错误时,默认展示付费墙(或根据需求调整) Superwall.shared.showPaywall() } }
注意事项
- 确保RevenueCat已正确初始化用户ID,避免匿名用户的状态混乱
- 离线时依赖缓存状态,保证逻辑正常运行
- 确认"subPlan"权益ID与RevenueCat后台配置完全一致
内容的提问来源于stack exchange,提问作者Carles - PLAVED
相关产品推荐
相关产品推荐

