ios - 在显示按钮之前检查是否可以进行应用内购买

标签 ios swift in-app-purchase storekit

我正在 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/

相关文章:

ios - 将 swift 连接到 FirebaseDatabase

ios - 我试图在滚动页面时更改 ImageView 高度

ios - 对于数字票务市场,我应该/必须使用什么支付网关?

android - 静态代码中的应用内购买错误

android - Gdx-pay/openIAB 在为亚马逊配置时打开谷歌播放对话框

ios - 一般来说,Apple 将支持使用旧 Xcode 提交应用程序多长时间?

testing - Swift 中的功能测试。模拟应用程序流程

swift - 如何重写 Swift++ 运算符? : ternary operator

ios - NEVPNManager 在 Swift 中连接到 VPN

ios - 将 EKRecurrenceRules 与云服务同步 RFC 2445 iCalendar 规范 RRULE