предупреждение, подтверждающее покупку в приложении, никогда не появляется - PullRequest
1 голос
/ 25 марта 2019

У меня есть обычный код наблюдателя очереди в магазине:

func paymentQueue(_ queue: SKPaymentQueue, 
    updatedTransactions transactions: [SKPaymentTransaction]) {
        for t in transactions {
            switch t.transactionState {
            case .purchasing, .deferred: break // do nothing
            case .purchased, .restored:
                let p = t.payment
                if p.productIdentifier == myProductID {
                    // ... set UserDefaults to signify purchase ...
                    // ... put up an alert thanking the user ...
                    queue.finishTransaction(t)
                }
            case .failed:
                queue.finishTransaction(t)
            }
        }
}

Проблема в том, что делать, когда у меня есть комментарий: «Подать предупреждение благодаря пользователю».Это кажется достаточно простым: я создаю UIAlertController и вызываю present, чтобы показать его.Но иногда это не появляется!

Проблема, похоже, связана с тем, что среда выполнения выдает свое собственное предупреждение («Все готово»).Я не получаю никакого уведомления об этом, поэтому я не знаю, что это происходит.Как я могу сделать так, чтобы мой UIAlertController был точно представлен?

1 Ответ

2 голосов
/ 25 марта 2019

Проблема

Вы указали на серьезную проблему времени и информации о покупках в приложении и StoreKit.

Что здесь не так, так это то, что вы (наблюдатель магазина) получаете paymentQueue(_:updatedTransactions:), и в этот момент две вещи происходят одновременно , что приводит к состоянию гонки:

  • Среда выполнения выдает предупреждение «Все готово».

  • Вы пытаетесь установить свой UIAlertController (и запускаете различные другие действия).

Как вы правильно сказали, вы не получите какого-либо события, которое сообщит вам, когда пользователь отклонил предупреждение среды выполнения «Все готово». Итак, как вы можете сделать что-то после , когда оповещение закончилось?

Более того, если вы попытаетесь установить свое оповещение в то же время, когда система выдает свое предупреждение «Все готово», вы молча выйдете из строя - ваше предупреждение UIAlertController никогда не появится .

Решение

Решение состоит в том, чтобы распознать, что, хотя системное предупреждение «Вы все настроены», ваше приложение деактивировано . Мы можем обнаружить этот факт и зарегистрироваться, чтобы получать уведомление , когда ваше приложение будет снова активировано. И , что - это момент, когда пользователь отклонил предупреждение «Все готово»!

Таким образом, теперь безопасно выставить предупреждение UIAlertController.

Вот так (использует мою утилиту delay, см. https://stackoverflow.com/a/24318861/341994; vc - контроллер представления, над которым мы собираемся представить предупреждение):

let alert = UIAlertController( // ...
// ... configure your alert here ...
delay(0.1) { // important! otherwise there's a race and we can get the wrong answer
    if UIApplication.shared.applicationState == .active {
        vc.present(alert, animated:true)
    } else { // if we were deactivated, present only after we are reactivated
        var ob : NSObjectProtocol? = nil
        ob = NotificationCenter.default.addObserver(
            forName: UIApplication.didBecomeActiveNotification, 
            object: nil, queue: nil) { n in
                NotificationCenter.default.removeObserver(ob as Any)
                delay(0.1) { // can omit this delay, but looks nicer
                    vc.present(alert, animated:true)
                }
            }
    }
}

Я неоднократно проверял этот подход (хотя и с трудом, потому что тестирование комплектов магазина работает так плохо), и он кажется абсолютно надежным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...