codiction
codiction

Reputation: 621

Check availability in switch statement

if a Enum type add new case in new os version,how to check availability in switch statement? Like a Enum in StoreKit below

public enum Code : Int {
    public typealias _ErrorType = SKError
    case unknown
    case clientInvalid 
    case paymentCancelled 
    case paymentInvalid 
    case paymentNotAllowed
    case storeProductNotAvailable
    @available(iOS 9.3, *)
    case cloudServicePermissionDenied 
    @available(iOS 9.3, *)
    case cloudServiceNetworkConnectionFailed
    @available(iOS 10.3, *)
    case cloudServiceRevoked
}

Is below code the only solution? It's too redundant.

if #available(iOS 10.3, *) {
    switch code {
        //all cases available in 10.3
        ...
    }
} else if #available(iOS 9.3, *) {
    switch code {
       //all cases available in 9.3
       ...
    }
} else {
    switch code {
        //all cases available below 9.3
        ...
    }
}

-----------------new-------------------------

I think It's not a question. All cases writed in one switch is fine, if statement is unneccessary. Because new added cases would not called in low iOS version.

Upvotes: 20

Views: 5333

Answers (3)

Max Potapov
Max Potapov

Reputation: 1337

Usually it happens on a new versions of Xcode with fresh SDK and toolchain. So, for example Xcode 12 is bundled with iOS 14 SDK and Swift 5.3 and has a similar issues with new cases like PHAuthorizationStatus.limited which marked as available only in iOS 14 and it will break switch statement without default case.

As a workaround to make both version of Xcode 11 and Xcode 12 working I'd like to suggest following solution with checking Swift version:

    switch PHPhotoLibrary.authorizationStatus() {
    case .authorized:
        presentImagePicker()
    case .denied:
        presentAccessDeniedAlert()
    case .notDetermined:
        requestAuthorization()
    case .restricted:
        break
#if swift(>=5.3) // Xcode 12 iOS 14 support
    case .limited:
        presentImagePicker()
#endif
    @unknown default:
        assertionFailure()
    }

Upvotes: 7

dn.Jung
dn.Jung

Reputation: 49

How about this?

if error.code == SKError.unknown {

} else if error.code == SKError.clientInvalid {

} else if error.code == SKError.paymentCancelled {

} else if error.code == SKError.paymentInvalid {

} else if error.code == SKError.paymentNotAllowed {

} else if error.code == SKError.storeProductNotAvailable {

} else if #available(iOS 9.3, *), error.code == SKError.cloudServicePermissionDenied {

} else if #available(iOS 9.3, *), error.code == SKError.cloudServiceNetworkConnectionFailed {

} else if #available(iOS 10.3, *), error.code == SKError.cloudServiceRevoked {

}

Upvotes: -1

Lyck
Lyck

Reputation: 728

I suppose you could do like this:

switch transactionCode {
    case SKError.unknown:
        //Handle case
    //(rest of ios < 9.3 available types)
    default:
        if #available(iOS 9.3, *) {
            if transactionCode == SKError.cloudServiceNetworkConnectionFailed {
                //Handle case
            }
            else if transactionCode == SKError.cloudServicePermissionDenied {
                //Handle case
            }
        }
        if #available(iOS 10.3, *) {
            if transactionCode == SKError.cloudServiceRevoked {
                //Handle case
            }
        }
    }

You are unable to make an exhaustive switch statement without the default case, but theres no redundant code.

Upvotes: 3

Related Questions