我在ios应用中实现了In-App-Purchase。在这里,我使用了RequestCompletionHandler
SKProductsRequestDelegate
方法,如下所示。有些时候应用程序因nil
值而崩溃。我的代码出了什么问题?
completionHandler
声明为:fileprivate var completionHandler: RequestCompletionHandler!
func productsRequest(_ request: SKProductsRequest!, didReceive response: SKProductsResponse!) {
print("Successfully loaded list of products..")
productsRequest = nil
if response.products.count > 0 {
if let skProducts = response.products as? [SKProduct] {
for product in skProducts {
print("found product: \(product.productIdentifier), \(product.localizedTitle), \(product.price.floatValue)")
}
completionHandler(true, skProducts as NSArray) //unexpectedly found nil while unwrapping an optional value exception getting in this line
completionHandler = nil
}
}
}
请参阅下面的屏幕截图以便更好地理解:
答案 0 :(得分:1)
如果完成处理程序可以是nil
我建议使用if let
,或者在您的情况下使用可选方法调用:
completionHandler?(true, skProducts as NSArray)
由于您使用了隐式解包的可选项(在!
声明中使用了completionHandler
),因此行completionHandler(true, skProducts as NSArray)
与completionHandler!(true, skProducts as NSArray)
相同,忽略了completionHandler
的可能性}可能是nil
并尝试执行它。如果completionHandler
为nil
,则会崩溃。除非你可以100%确定它永远不会是nil
,否则永远不要使用隐式展开。
此外,我强烈建议不要使用隐式展开的类型作为属性类型,除非你有充分的理由这样做。在这种情况下,显然completionHandler
可以是nil
。而是将声明更改为可选:
fileprivate var completionHandler: RequestCompletionHandler?
答案 1 :(得分:0)
您将completionHandler声明为RequestCompletionHandler!
这意味着你告诉编译器:“completionHandler可能是零,但我绝对百分之百确定它不是我每次使用它,所以如果我使用它而它是零,那么请给我一个赞成并使应用程序崩溃“。
这正是编译器正在做的事情。当它为零时,你不应该调用completionHandler。你忘了设置它,或者它是故意设置它(但这是非常非常不可能),那么你需要检查它是否为零。