我正在 XCode 项目中实现应用内购买,除了一个错误之外,一切正常。当用户未连接到互联网并单击购买按钮时,应用程序会崩溃。我相信发生这种情况是因为应用内购买尚未从 iTunes 获取,并且单击按钮无法运行购买流程。当用户在商店屏幕加载的第一秒单击按钮时,也会发生这种崩溃,因为 - 我认为 - 需要一些时间来获取(或请求)产品。这就是我要说的:
override func didMove(to view: SKView) {
...
fetchAvailableProducts()
}
func fetchAvailableProducts() {
// Put here your IAP Products ID's
let productIdentifiers = NSSet(objects:
productID100,
productID250,
productID500,
productIDRemoveAds,
productIDUnlockAll)
productsRequest = SKProductsRequest(productIdentifiers: productIdentifiers as! Set<String>)
productsRequest.delegate = self
productsRequest.start()
}
我的代码基于 this tutorial .
有没有办法更改我的代码以使其“防崩溃”,以便它首先检查是否可以购买产品以让您使用该按钮?
最佳答案
我使用 SwiftyStorkeKit ( https://github.com/bizz84/SwiftyStoreKit ),它使用完成处理程序来填写产品(也可以让您免于重新发明轮子 - 并且是一个很好的学习资源)
对于检查网络连接,我使用 Apple 的 Reachability ( https://developer.apple.com/library/content/samplecode/Reachability/Introduction/Intro.html )。这是实现的相关部分。它还检查应用程序失去焦点的情况。您还可以在任何商店操作之前使用网络检查。
class vcon: UIViewController {
@IBOutlet weak var noConnectionView: UIView!
func isNetworkAvailable() -> Bool {
//quick test if network is available
var netTest:Reachability? = Reachability(hostName: "apple.com")!
if netTest?.currentReachabilityStatus == .notReachable {
netTest = nil
return false
}
netTest = nil
return true
}
func displayNoNetworkView() {
//this example pulls from a storyboard to a view I have in front of everything else at all times, and shows the view to block everything else if the network isnt available
let ncvc = UIStoryboard(name: "HelpPrefsInfo", bundle: nil).instantiateViewController(withIdentifier: "noNetworkVC") as! noNetworkVC
ncvc.view.frame = noConnectionView.bounds
ncvc.view.backgroundColor = color03
ncvc.no_connection_imageView.tintColor = color01
ncvc.noInternetConnection_label.textColor = color01
noConnectionView.addSubview(ncvc.view)
}
func hideDataIfNoConnection() {
//the actual code that displays the no net connection view
if !isNetworkAvailable() {
if noConnectionView.isHidden == true {
noConnectionView.alpha = 0
noConnectionView.isHidden = false
self.iapObjects = []
UIView.animate(withDuration: 0.50, animations: {
self.noConnectionView.alpha = 1
}, completion:{(finished : Bool) in
});
}
} else {
if noConnectionView.isHidden == false {
self.collection_view.reloadData()
UIView.animate(withDuration: 0.50, animations: {
self.noConnectionView.alpha = 0
}, completion:{(finished : Bool) in
self.noConnectionView.isHidden = true
self.loadIAPData()
});
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground), name: .UIApplicationDidBecomeActive, object: nil)
displayNoNetworkView()
loadIAPData()
}
func loadIAPData() {
load the data if the network is available
if isNetworkAvailable() {
helper.requestProductsWithCompletionHandler(completionHandler: { (success, products) -> Void in
if success {
self.iapObjects = products!
self.collection_view.reloadData()
} else {
let alert = UIAlertController(title: "Error", message: "Cannot retrieve products list right now.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
self.present(alert, animated: true, completion: nil)
}
})
}
}
func willEnterForeground() {
hideDataIfNoConnection()
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
hideDataIfNoConnection()
}
关于ios - 在显示按钮之前检查是否可以进行应用内购买,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45890290/