在推迟来自 App Store 的推广 IAP 请求时显示提醒

Show an alert when deferring a Promoted IAP request from App Store

我们正在实施 Apple 的新“Promoted In-App Purchases”系统,允许用户单击 Apple App Store 中的 "Buy" 按钮触发购买 IAP。

系统要求应用实现 SKPaymentTransactionObserverpaymentQueue:shouldAddStorePayment:forProduct: 委托方法,return 是一个布尔值。文档说,

Return true to continue the transaction in your app.

Return false to defer or cancel the transaction.

如果我们只是 return false,用户会看到我们的应用程序进入前台,然后就什么也没有发生了。默认情况下,OS 不会弹出 "Purchase canceled" 之类的消息;我想,它把决定权留给了应用程序开发人员。

App Store Promoted IAP 购买请求可以随时到达,包括当用户正处于不应中断的流程中时。从这个方法到 return false 是一个完美的案例。当我这样做时,我想向用户显示一条警告消息,用 UIAlertController.

解释问题

问题是,我的 paymentQueue:shouldAddStorePayment:forProduct: 中没有可使用的上下文视图控制器。通常,当我想从视图控制器内部显示警报时,我会调用 [self presentViewController:alert animated:YES completion:nil];,但是此委托方法中的 selfSKPaymentTransactionObserver,而不是视图控制器,因此不行。

我什至不确定当此委托方法触发时是否 有保证的活动视图控制器。据我所知,委托方法可以在 applicationDidBecomeActive 事件之前触发。

当 returning false 来自 paymentQueue:shouldAddStorePayment:forProduct: 时,显示警报(或 UI 的任何其他片段)的最佳方式是什么?

您可以 get the application window's root view controller 并使用它来显示警报。

Objective-C

id *rootController = [[[[UIApplication sharedApplication]delegate] window] rootViewController];
[rootViewController presentViewController:alertController animated:YES completion:nil];

Swift

let appDelegate  = UIApplication.sharedApplication().delegate
let viewController = appDelegate.window!.rootViewController
viewController.presentViewController(alertController, animated: true, completion: nil)

有一个符合 SKPaymentTransactionObserver 的 class 的共享实例。将推广的付款存储在此共享实例的可选变量中。

class StoreHelper: NSObject, SKPaymentTransactionObserver {

    static let shared = StoreHelper()

    private var promotedPayment: SKPayment?

    var hasPromotedPayment: Bool {
        return promotedPayment != .none
    }

    override init() {
        super.init()

        SKPaymentQueue.default().add(self)
    }

    func paymentQueue(_ queue: SKPaymentQueue, shouldAddStorePayment payment: SKPayment, for product: SKProduct) -> Bool {
        promotedPayment = payment

        return false
    }

    func beginPurchaseForPromotedPayment() {
        ...
    }
}

将显示代码放在出现的第一个视图控制器的 viewDidAppear 中。

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

    if StoreHelper.shared.hasPromotedPayment {
        // your presentation code

        StoreHelper.shared.beginPurchaseForPromotedPayment()

        // after completion, remove promoted product from store helper
    }
}

快乐编码