Accessing code in Swift 3 Error
SwiftSwift3Swift Problem Overview
New in Xcode 8 beta 4, NSError
is bridged to the Swift Error
protocol type. This affects StoreKit when dealing with failed SKPaymentTransaction
s. You ought to check to be sure the error didn't occur because the transaction was cancelled to know whether or not to show an error message to the user. You do this by examining the error's code
. But with Error
instead of NSError
, there is no code
defined. I haven't been able to figure out how to properly get the error code from Error
.
This worked in the previous version of Swift 3:
func failedTransaction(_ transaction: SKPaymentTransaction) {
if let transactionError = transaction.error {
if transactionError.code != SKErrorCode.paymentCancelled.rawValue {
//show error to user
}
}
...
}
Now that error
is an Error
not NSError
, code
is not a member.
Swift Solutions
Solution 1 - Swift
Another option to access code and domain properties in Swift 3 Error types is extending it as follow:
extension Error {
var code: Int { return (self as NSError).code }
var domain: String { return (self as NSError).domain }
}
Solution 2 - Swift
Now in Xcode 8 and swift 3 the conditional cast is always succeeds, so you need do following:
let code = (error as NSError).code
and check the code
for your needs. Hope this helps
Solution 3 - Swift
Casting to SKError
seems to be working for me in xCode 8 and Swift 3...
guard let error = transaction.error as? SKError else {return}
switch error.code { // https://developer.apple.com/reference/storekit/skerror.code
case .unknown: break
case .paymentCancelled: break
case .clientInvalid: break
case .paymentInvalid: break
case .paymentNotAllowed: break
case .cloudServiceNetworkConnectionFailed: break
case .cloudServicePermissionDenied: break
case .storeProductNotAvailable: break
}
No need for rawValue
.
Solution 4 - Swift
This is correct (Apple's own tests use this approach):
if error._code == SKError.code.paymentCancelled.rawValue { ... }
On the other hand, casting to NSError will probably be deprecated soon:
let code = (error as NSError).code // CODE SMELL!!
if code == SKError.code.paymentCancelled.rawValue { ... }
Solution 5 - Swift
Use
> error._code == NSURLErrorCancelled
to match the error code.
Solution 6 - Swift
A lot is changing. Here's update for Xcode 11.
if let skError = transaction.error as? SKError, skError.code == .paymentCancelled { print("Cancelled") }
Solution 7 - Swift
enum CheckValidAge : Error{
case overrage
case underage
}
func checkValidAgeForGovernmentJob(age:Int)throws -> Bool{
if age < 18{
throw CheckValidAge.underage
}else if age > 25{
throw CheckValidAge.overrage
}else{
return true
}
}
do {
try checkValidAgeForGovernmentJob(age: 17)
print("You are valid for government job ")
}catch CheckValidAge.underage{
print("You are underage for government job ")
}catch CheckValidAge.overrage{
print("You are overrage for government job ")
}
try checkValidAgeForGovernmentJob(age: 17) OutPut : You are underage for government job
try checkValidAgeForGovernmentJob(age: 26) OutPut : You are overrage for government job
try checkValidAgeForGovernmentJob(age: 18) OutPut : You are valid for government job