请求完成处理程序致命错误:在解包可选值异常时意外发现nil

时间:2018-03-02 12:35:02

标签: ios swift swift3 in-app-purchase swift4

我在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
        }
    }
}

请参阅下面的屏幕截图以便更好地理解:

enter image description here

2 个答案:

答案 0 :(得分:1)

如果完成处理程序可以是nil我建议使用if let,或者在您的情况下使用可选方法调用:

completionHandler?(true, skProducts as NSArray)

由于您使用了隐式解包的可选项(在!声明中使用了completionHandler),因此行completionHandler(true, skProducts as NSArray)completionHandler!(true, skProducts as NSArray)相同,忽略了completionHandler的可能性}可能是nil并尝试执行它。如果completionHandlernil,则会崩溃。除非你可以100%确定它永远不会是nil,否则永远不要使用隐式展开。

此外,我强烈建议不要使用隐式展开的类型作为属性类型,除非你有充分的理由这样做。在这种情况下,显然completionHandler可以是nil。而是将声明更改为可选:

fileprivate var completionHandler: RequestCompletionHandler?

答案 1 :(得分:0)

您将completionHandler声明为RequestCompletionHandler!

这意味着你告诉编译器:“completionHandler可能是零,但我绝对百分之百确定它不是我每次使用它,所以如果我使用它而它是零,那么请给我一个赞成并使应用程序崩溃“。

这正是编译器正在做的事情。当它为零时,你不应该调用completionHandler。你忘了设置它,或者它是故意设置它(但这是非常非常不可能),那么你需要检查它是否为零。