Search code examples
swiftstorekit

Pattern cannot match values of type 'SKError'


I am getting the error

Pattern cannot match values of type 'SKError'

However, when I looked up the code for SKError with store kit I have typed in the errors correctly and could not find a solution. (Getting 4 errors - Pattern cannot match values of type 'SKError' - for each case in switch error).

func alertForPurchaseResult(result : PurchaseResult) -> UIAlertController {
    switch result {
    case .success(let product):
        print("Purchase Succesful: \(product.productId)")

        return alertWithTitle(title: "Thank You", message: "Purchase completed")
        break
    case .error(let error):
        print("Purchase Failed: \(error)")
        switch error {
        case .failed(let error):
            if (error as NSError).domain == SKErrorDomain {
                return alertWithTitle(title: "Purchase Failed", message: "Check your internet connection or try again later.")
            }
            else {
                return alertWithTitle(title: "Purchase Failed", message: "Unknown Error. Please Contact Support")
            }
            break
        case .invalidProductId(let productID):
            return alertWithTitle(title: "Purchase Failed", message: "\(productID) is not a valid product identifier")
            break
        case .noProductIdentifier:
            return alertWithTitle(title: "Purchase Failed", message: "Product not found")
        break
        case .paymentNotAllowed:
            return alertWithTitle(title: "Purchase Failed", message: "You are not allowed to make payments")
            break

        }
        break
    }
}




func purchase(purchase: RegisteredPurchase){
       NetworkActivityIndicatorManager.NetworkOperationStarted()
       SwiftyStoreKit.purchaseProduct(bundleID + "." + purchase.rawValue, completion: {
        result in
        NetworkActivityIndicatorManager.NetworkOperationFinished()

        if case .success(let product) = result {
            if product.needsFinishTransaction{
                SwiftyStoreKit.finishTransaction(product.transaction)
            }
            self.showAlert(alert: self.alertForPurchaseResult(result: result))
        }
    })
}

Solution

  • I’m inferring that your PurchaseResult is something like:

    typealias PurchaseResult = CustomResult<Product, SKError>
    

    (I don’t know what your Result type is, but all I know is that the standard Result type is .failure or .success, and yours has .error instead of .failure.)

    I’m also assuming that you must have your own error type, e.g.:

    enum MyAppError: Error {
        case invalidProductId(String)
        case noProductIdentifier
        case paymentNotAllowed
    }
    

    So, I’d first change PurchaseResult to allow any relevant error types:

    typealias PurchaseResult = CustomResult<Product, Error>
    

    And then handle the various types of errors

    func alertForPurchaseResult(result: PurchaseResult) -> UIAlertController {
        switch result {
        case .success(let product):
            return alertWithTitle(title: "Thank You", message: "Purchase completed")
    
        case .error(let error as SKError):
            switch error.code {
            case .unknown:
                <#code#>
            case .clientInvalid:
                <#code#>
            case .paymentCancelled:
                <#code#>
            case .paymentInvalid:
                <#code#>
            case .paymentNotAllowed:
                <#code#>
            case .storeProductNotAvailable:
                <#code#>
            case .cloudServicePermissionDenied:
                <#code#>
            case .cloudServiceNetworkConnectionFailed:
                <#code#>
            case .cloudServiceRevoked:
                <#code#>
            case .privacyAcknowledgementRequired:
                <#code#>
            case .unauthorizedRequestData:
                <#code#>
            case .invalidOfferIdentifier:
                <#code#>
            case .invalidSignature:
                <#code#>
            case .missingOfferParams:
                <#code#>
            case .invalidOfferPrice:
                <#code#>
            @unknown default:
                <#code#>
            }
    
        case .error(let error as MyAppError):
            switch error {
            case .invalidProductId(let productID):
                return alertWithTitle(title: "Purchase Failed", message: "\(productID) is not a valid product identifier")
    
            case .noProductIdentifier:
                return alertWithTitle(title: "Purchase Failed", message: "Product not found")
    
            case .paymentNotAllowed:
                return alertWithTitle(title: "Purchase Failed", message: "You are not allowed to make payments")
            }
    
        case .error:
            return alertWithTitle(title: "Purchase Failed", message: "Unknown Error. Please Contact Support.")
        }
    }
    

    The @unknown keyword in if you’re using Swift 5. You can omit that if using earlier Swift versions.

    By the way, if you’re wondering about that SKError enumerations, when I did a switch for the .code of the SKError, it gave me a “fix” suggestion and it populated all those for me.