bizz84 / SwiftyStoreKit

Lightweight In App Purchases Swift framework for iOS 8.0+, tvOS 9.0+ and macOS 10.10+ ⛺
MIT License
6.57k stars 796 forks source link

When will be deinit to call SKPaymentQueue.remove(_:) method of the instance 'InAppCompleteTransactionsObserver'? #124

Closed Arcovv closed 7 years ago

Arcovv commented 7 years ago

Platform

In app purchase type

Environment

Version

0.2.10

Report

Issue summary

Very grateful to this framework, is indeed very easy to use. I originally used this framework for IAP, but later the company's business has re-written a, for comparison, I found that in dealing with 'SKPaymentQueue.remove' there are some differences. Here I have some design problems would like to ask about.

The instance which type of 'InAppCompleteTransactionsObserver' seems like will call SKPaymentQueue.remove method when it will be deinit. But it's the variable optional property of 'SwiftyStoreKit'. When set more 'SwiftyStoreKit.completeTransactions', 'InAppCompleteTransactionsObserver' instance will be nil and removed from SKPaymentQueue?

Recently in the framework of my own design, a few user's app will crash on launch everytime even if the user reinstalls the App and reboots. After some information on the query and you design the framework of the match, I found a single case in the design and 'SKPaymentQueue.remove' very different. I used a singleton to handle all of the 'SKPaymentTransactionObserver' events, but since the singleton rarely triggers 'deinit', I have never used 'SKPaymentQueue.remove', and the result is a crash. I ask is not for this reason I now have been the collapse of the situation? If so, when should I take the initiative to remove? Hope to get some advice.

Here I find some relevant information:

Http://aplus.rs/2012/a-single-bug-in-my-storekit-code-that-lost-me-90-of-iap-sales/ Http://stackoverflow.com/questions/24101185/strange-crash-reports-on-in-app-purchase-code Http://stackoverflow.com/questions/19203921/in-app-purchase-iap-process-appears-to-be-crashing-the-app-on-launch-for-one-o Http://stackoverflow.com/questions/19817130/following-in-app-purchase-app-crashing-on-startup-productidentifier-nil Http://stackoverflow.com/questions/34289204/in-app-purchase-causes-occasional-crash Http://stackoverflow.com/questions/4988663/skpaymentqueue-addtransactionobserver-asking-for-app-store-password-on-startup-a

Thank you very much for your help.

bizz84 commented 7 years ago

@YueJun1991 As SwiftyStoreKit is effectively a singleton and it holds a reference to InAppCompleteTransactionsObserver as soon as you call completeTransactions(), deinit is never called.

Note that completeTransactions() is only called in AppDelegate in the demo app. This is because the payment queue should be registered as soon as the app starts.

It would be incorrect to call completeTransactions() from a view controller or any object that can be deallocated before the callback is received. I'm not sure what your use case is but if you need to do this, make sure you use weak self to prevent retain cycles:

SwiftyStoreKit.completeTransactions() { [weak self] result in

}

The same applies for all the other methods in SwiftyStoreKit as they are all asynchronous.

I hope this clarifies things.

bizz84 commented 7 years ago

All of this will change soon. Hopefully this PR will fix things:

https://github.com/bizz84/SwiftyStoreKit/pull/131

Testing welcome :)

bizz84 commented 7 years ago

@YueJun1991 could you verify if this is still an issue on version 0.7.0?

Arcovv commented 7 years ago

Hi @bizz84

This time because of holiday and work reasons, there is no way even to reply to you, I am very sorry, but also hope to have more time to test my guess.

When asked questions, I have modified and tested my code, mainly to verify that my solution is complete.

Since my company's project is still using Swift 2.3, I'm not sure if this is one of the reasons for the crash, after all, Swift 3 API improvements are huge.

At the beginning, I found that I did not reasonably remove the observer from the paymentQueue, but then I found that the problem still existed.

After continuing to study the relevant information, I found something very interesting:

First, I looked at the case of Apple's In-App Purchase Best Practices and modified my program in accordance with his specifications in.

Then I have anti-compiled StoreKit look at addObserver and removeObserver related content, but it seems that did not find useful things.

Our customers later contacted me and found that multiple devices with VPN would seem to affect IAP this problem, but I'm not sure.

In addition, I found that the crash function mainly occurs in dealing with the failedTransaction, and later found other article mentions the problem of calling paymentTransaction

And there is another article article seems to have mentioned the problem.

The last reason to guess is that the distribution mechanism of Swift may have some effect, and I'm not sure.

At the end of the question, my app will still happen from time to time to crash, but will not open the App continued to crash.

Finally if you need me to provide my crash log, also hope you can contact me directly.

I'm so sorry I was so late to reply to you.

Hope to help you.