Swift中如何在switch语句内使用#available?求多平台适配方案
在Swift Switch语句中使用#available适配iOS的解决方案
原代码的核心问题是无法直接在switch的case块中插入#available条件判断——这不符合Swift语法规范。针对EKEventStore在iOS17+/macOS13+新增的.fullAccess和.writeOnly权限状态,以下两种适配方案均无需拆分多个独立switch语句。
方案一:用where子句结合#available
直接在case后添加where条件,限制该case仅在指定系统版本生效。旧系统会自动忽略这些新case,直接走到@unknown default分支。
private func checkStatusAndGetAllEvents() -> String { var eventResult: String = "What?" let currentStatus = EKEventStore.authorizationStatus(for: .event) switch currentStatus { case .authorized: eventResult = "authorized" case .notDetermined: eventResult = "notDetermined" eventStore.requestAccess(to: .event) { accessGranted, error in // 注意:requestAccess是异步方法,原代码直接赋值eventResult不会生效 // 需切换主线程更新,或改用闭包/async-await返回结果 DispatchQueue.main.async { eventResult = accessGranted ? "notDetermined granted" : "Change Settings to Allow Access" } } case .restricted: eventResult = "restricted" case .denied: eventResult = "denied" // iOS17+/macOS13+专属case case .fullAccess where #available(iOS 17, macOS 13, *): eventResult = "fullAccess" case .writeOnly where #available(iOS 17, macOS 13, *): eventResult = "writeOnly" @unknown default: eventResult = "default" } return eventResult }
方案二:在@unknown default中嵌套switch
若觉得where子句不够直观,可将新状态的处理逻辑放在@unknown default分支内,通过嵌套switch配合可用性检查实现适配:
private func checkStatusAndGetAllEvents() -> String { var eventResult: String = "What?" let currentStatus = EKEventStore.authorizationStatus(for: .event) switch currentStatus { case .authorized: eventResult = "authorized" case .notDetermined: eventResult = "notDetermined" eventStore.requestAccess(to: .event) { accessGranted, error in DispatchQueue.main.async { eventResult = accessGranted ? "notDetermined granted" : "Change Settings to Allow Access" } } case .restricted: eventResult = "restricted" case .denied: eventResult = "denied" @unknown default: if #available(iOS 17, macOS 13, *) { switch currentStatus { case .fullAccess: eventResult = "fullAccess" case .writeOnly: eventResult = "writeOnly" default: eventResult = "default" } } else { eventResult = "default" } } return eventResult }
额外注意点
原代码中requestAccess(to:completion:)是异步方法,方法返回eventResult时,异步回调尚未执行,因此回调内的赋值不会影响返回值。若需要获取异步操作后的结果,建议改用闭包回调或async/await异步方法,示例如下:
private func checkStatusAndGetAllEvents(completion: @escaping (String) -> Void) { let currentStatus = EKEventStore.authorizationStatus(for: .event) switch currentStatus { case .authorized: completion("authorized") case .notDetermined: eventStore.requestAccess(to: .event) { accessGranted, error in DispatchQueue.main.async { completion(accessGranted ? "notDetermined granted" : "Change Settings to Allow Access") } } case .restricted: completion("restricted") case .denied: completion("denied") case .fullAccess where #available(iOS 17, macOS 13, *): completion("fullAccess") case .writeOnly where #available(iOS 17, macOS 13, *): completion("writeOnly") @unknown default: completion("default") } }
内容的提问来源于stack exchange,提问作者iPadawan
相关产品推荐
相关产品推荐

