我正在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。
有没有办法更改我的代码以使其“防崩溃”,以便它首先检查是否可以购买产品以让您使用按钮?
答案 0 :(得分:0)
我使用SwiftyStorkeKit(https://github.com/bizz84/SwiftyStoreKit),它使用完成处理程序来填充产品(也可以避免重新发明轮子 - 并且是一个很好的资源来学习)
至于检查网络连接,我使用Apple的可达性(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()
}