0

I've implemented In-App-Purchase in my ios app. Here I've used RequestCompletionHandler at SKProductsRequestDelegate method as shown below. Some times app getting crash because nil value. What is wrong in my code?

completionHandler is declared as: 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
        }
    }
}

See the screenshot below for better understanding:

enter image description here

ks1322
  • 33,961
  • 14
  • 109
  • 164
  • Possible duplicate of [What does "fatal error: unexpectedly found nil while unwrapping an Optional value" mean?](https://stackoverflow.com/questions/32170456/what-does-fatal-error-unexpectedly-found-nil-while-unwrapping-an-optional-valu) – Cristik Mar 02 '18 at 12:47

2 Answers2

1

If completion handler can be nil I recommend to either use if let, or in your case optional method call:

completionHandler?(true, skProducts as NSArray)

Since you used implicitly unwrapped optional (you used ! in completionHandler declaration), line completionHandler(true, skProducts as NSArray) is the same as completionHandler!(true, skProducts as NSArray) which ignores the possibility that completionHandler might be nil and tries to execute it. If completionHandler is nil, it crashes. Unless you can be 100% sure that it will never be nil, never use implicit unwrap.

Moreover, I would strongly recommend not to use implicitly unwrapped types as property types, unless you have a really good reason for doing so. In this case obviously the completionHandler can be nil. Rather change the declaration to an optional:

fileprivate var completionHandler: RequestCompletionHandler?
Milan Nosáľ
  • 19,169
  • 4
  • 55
  • 90
  • It depends. It's fine if it is a bug when it's nil, you will be told at runtime. As the OP was. Now if someone doesn't know the difference between ? and !, that's tough. – gnasher729 Mar 02 '18 at 12:44
0

You declared completionHandler as RequestCompletionHandler!

That means you are telling the compiler: "completionHandler could be nil, but I'm absolutely one hundred percent sure it isn't whenever I use it, so if I use it while it is nil, then please do me a favour and crash the application".

And that's exactly what the compiler is doing. You shouldn't be calling completionHandler when it's nil. Either you forgot to set it, or it is intentional that it isn't set (but that is very very very unlikely), then you need to check that it is nil.

gnasher729
  • 51,477
  • 5
  • 75
  • 98