2016-03-06 124 views
1

我有一个应用程序被释放和应用程序内购买似乎在用户已购买的场合工作,但我注意到应用程序不断崩溃,Crashlytics(面料)Crashlytics为什么因为我无法在任何设备上复制崩溃。这是我第一次进行应用内购买的整合,因此对我很有帮助。应用内购买崩溃偶尔

我无法弄清楚什么是错的,特别是因为没有特定设备的模式,有时它工作,有时它不(显然)。我知道这可能有多种原因,但向正确的方向微调会很好。 这里的崩溃日志

Thread : Crashed: com.apple.main-thread 
0 app       0xc2658 WelcomeViewController.purchaseAlert() ->() (WelcomeViewController.swift) 
1 app       0xc2658 WelcomeViewController.purchaseAlert() ->() (WelcomeViewController.swift) 
2 app       0xc1148 @objc WelcomeViewController.removeAdsTapped(UIButton) ->() (WelcomeViewController.swift:164) 
3 UIKit       0x29691771 -[UIApplication sendAction:to:from:forEvent:] + 80 
4 UIKit       0x29691701 -[UIControl sendAction:to:forEvent:] + 64 
5 UIKit       0x2967961f -[UIControl _sendActionsForEvents:withEvent:] + 446 
6 UIKit       0x29691051 -[UIControl touchesEnded:withEvent:] + 616 
7 UIKit       0x29690cbf -[UIWindow _sendTouchesForEvent:] + 646 
8 UIKit       0x296895d7 -[UIWindow sendEvent:] + 642 
9 UIKit       0x2965a119 -[UIApplication sendEvent:] + 204 
10 UIKit       0x29658757 _UIApplicationHandleEventQueue + 5134 
11 CoreFoundation     0x25485257 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 14 
12 CoreFoundation     0x25484e47 __CFRunLoopDoSources0 + 454 
13 CoreFoundation     0x254831af __CFRunLoopRun + 806 
14 CoreFoundation     0x253d5bb9 CFRunLoopRunSpecific + 516 
15 CoreFoundation     0x253d59ad CFRunLoopRunInMode + 108 
16 GraphicsServices    0x2664faf9 GSEventRunModal + 160 
17 UIKit       0x296c1fb5 UIApplicationMain + 144 
18 app       0xbaba4 main (AppDelegate.swift:15) 
19 libdispatch.dylib    0x25088873 (Missing) 

任何东西,我很想念?

编辑:

这是当用户点击删除广告按钮得到什么叫

func purchaseAlert() { 


     let priceFormatter: NSNumberFormatter = { 

      let pf = NSNumberFormatter() 
      pf.formatterBehavior = .Behavior10_4 
      pf.numberStyle = .CurrencyStyle 
      return pf 


     }() 

     priceFormatter.locale = storeProducts.first!.priceLocale 

     let productPrice = storeProducts.first!.price 

     let price = priceFormatter.stringFromNumber(productPrice)! 

     let alert = UIAlertController(title: "Remove Ads for \(price)", message: "This purchase will remove all ad's that show through out the app", preferredStyle: .Alert) 

     alert.addAction(UIAlertAction(title: "Go Back", style: .Default, handler: nil)) 

     alert.addAction(UIAlertAction(title: "Remove Ad's", style: .Default, handler: { (_) -> Void in 


      self.removeADs() 

     })) 




     self.presentViewController(alert, animated: true, completion: nil) 

    } 

购买产品

func removeADs() { 

     let product = storeProducts.first 

     Purchasables.store.purchaseProduct(product!) 


    } 

这是假设总是会有一个产品,应该有。

更新: 我已经更新的应用程序,并等待一个多星期来获取一些数据和事实证明,用户仍然无法购买。我现在安全地解开所有可选项,所以没有零值,因此导致没有崩溃,但我一直在跟踪点击删除广告按钮,我注意到我得到了这样的东西(20taps,10个用户),表明用户不断地点击并导致没有购买。我也跟踪了解商店是否有产品退回,并且有97%的时间。我仍然无法指出问题,并且按钮上的按键绝对不是偶然的,因为删除广告按钮几乎没有问题。我仍然会购买一些产品,但大多数都会失败。

+0

你可以张贴一些你在应用内购买代码中的相关位。很难告诉你从这个错误 – crashoverride777

+0

当然,我已经添加了更多的代码。令我困惑的是,有些用户能够购买,而大部分用户却不能。我试过不同的商店不同的设备,仍然无法复制这个问题。 –

+1

由于你不能复制这个问题,所以你不会得到任何错误信息,看看发生了什么。令人沮丧的是,我知道我的游戏存在问题,因为我有一个苹果审查团队告诉我的错误,即我无法复制我的生活。 – crashoverride777

回答

1

仍然很难帮助您解决任何可以复制的崩溃或xCode错误。然而就像我说过的,你至少可以改进你的代码,以确保在值为零的情况下不会出现崩溃。

所以,你应该改变FUNC您购买警惕这种

func purchaseAlert() { 


    let priceFormatter: NSNumberFormatter = { 

     let pf = NSNumberFormatter() 
     pf.formatterBehavior = .Behavior10_4 
     pf.numberStyle = .CurrencyStyle 
     return pf 


    }() 

    /// safely unwrap storeProducts.first! to ensure its not nil 
    /// if its nil than exit the method 
    guard let firstStoreProduct = storeProducts.first! else { return } 

    // no more ! needed at the end which might caused a crash before 
    priceFormatter.locale = firstStoreProduct.priceLocale 

    // safely create the product price, if you can't exit the method 
    guard let productPrice = firstStoreProduct.price else { return } 

    // no more ! needed at the end which might also caused a crash before because product price cannot be nil anymore when getting to this line 
    let price = priceFormatter.stringFromNumber(productPrice) 


    let alert = UIAlertController(title: "Remove Ads for \(price)", message: "This purchase will remove all ad's that show through out the app", preferredStyle: .Alert) 

    alert.addAction(UIAlertAction(title: "Go Back", style: .Default, handler: nil)) 

    alert.addAction(UIAlertAction(title: "Remove Ad's", style: .Default, handler: { (_) -> Void in 


     self.removeADs() 

    })) 




    self.presentViewController(alert, animated: true, completion: nil) 

} 

正如你可以看到我使用2个警卫语句(一样的,如果让)安全地拆开包装的东西。我更喜欢这种方式,而不是使用“如果让”金字塔。如果你不喜欢这种方式,或者出于某种原因,如果出现错误,不希望早点返回该方法,则可以将其更改为“如果让”。

你删除广告的方法应该是这样的

func removeADs() { 

    if let product = storeProducts.first! { 

     Purchasables.store.purchaseProduct(product) 
    } 
} 

这样你摆脱一些!在没有确保它们不是零的情况下解开价值。 我需要看到你的数组或字典和相关的代码,可能会进一步确定什么可能是零。

+0

需要做到这一点,我很难遵循指导来设置iap,所以我要把它归咎于指南,呵呵。但在这种情况下,这有助于价值似乎为零,如果我会安全地解开选择权,我不知道用户无法购买。所以这就是为什么我需要跟踪删除广告的按钮上的水龙头。谢谢我会这样做,更新后,我会更新。 –

+1

没问题,让我们贴出来,如果它修复坠毁 – crashoverride777

+0

崩溃已修复,但问题仍然存在。我已经更新了我的帖子,如果你想被困惑一下。 –

0

我在1个月前有同样的问题,没有崩溃总是只在90%的情况下。这是一个苹果的错误,线程不会停止我不知道为什么...但要解决这个我取消请求(SKProductsRequest),它工作正常:

var request: SKProductsRequest! //global to cancel when disappear 
//request products when you want (viewDidLoad for example) 
request = SKProductsRequest(productIdentifiers: productID as! Set<String>) 
      request.delegate = self 
      request.start() 

消失视图控制器时:

override func viewDidDisappear(animated: Bool) { 
     super.viewDidDisappear(animated) 
     request.delegate = nil; 
     request.cancel() 
     SKPaymentQueue.defaultQueue().removeTransactionObserver(self) 
    }