You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中如何用Switch处理值相同但场景不同的枚举

问题:Swift枚举相同原始值导致分支无法触发的解决办法

问题核心

你定义的ApiType枚举遵循String协议时,.usemeInLogin和.usemeInLogout使用了相同的原始值"authenticationAccessIdApi",但Swift会将拥有相同原始值的枚举case视为同一个实例:当通过原始值初始化或传递枚举值时,系统只会匹配第一个定义的case(即.usemeInLogin),后续的.usemeInLogout永远不会被选中,这就是分支无法触发的原因。

解决方案

方案1:用关联值区分业务场景(推荐)

将两个相同原始值的case合并,通过关联值标记业务场景,同时保留原始值的兼容性:

enum ApiType: String, CaseIterable {
    case dashboard = "dashboardRootIdApi"
    case profile = "profileRootIdApi"
    case authentication(scene: String)
    
    // 重写rawValue,保证认证场景返回统一字符串
    override var rawValue: String {
        switch self {
        case .dashboard: return "dashboardRootIdApi"
        case .profile: return "profileRootIdApi"
        case .authentication: return "authenticationAccessIdApi"
        }
    }
    
    // 自定义初始化(若需从原始值转换,需额外上下文,否则返回nil)
    init?(rawValue: String) {
        switch rawValue {
        case "dashboardRootIdApi":
            self = .dashboard
        case "profileRootIdApi":
            self = .profile
        case "authenticationAccessIdApi":
            // 仅通过rawValue无法区分场景,建议直接用case创建实例
            return nil
        default:
            return nil
        }
    }
}

// 业务处理函数修改
func authenticationDtoScreen(for type: ApiType) -> UIControllerSharedScreen {
    switch type {
    case .authentication(scene: "login"):
        return UIControllerScreenConfiguration(for: type, title: "Login")
    case .authentication(scene: "logout"):
        return UIControllerScreenConfiguration(for: type, title: "Logout")
    default:
        fatalError("Unsupported API type")
    }
}

方案2:嵌套枚举拆分场景

把认证相关逻辑拆成子枚举,既保留统一原始值,又能明确区分场景:

enum ApiType: String, CaseIterable {
    case dashboard = "dashboardRootIdApi"
    case profile = "profileRootIdApi"
    case authentication(AuthenticationScene)
    
    enum AuthenticationScene: String {
        case login = "authenticationAccessIdApi"
        case logout = "authenticationAccessIdApi"
    }
    
    override var rawValue: String {
        switch self {
        case .dashboard: return "dashboardRootIdApi"
        case .profile: return "profileRootIdApi"
        case .authentication(let scene): return scene.rawValue
        }
    }
}

// 业务处理
func authenticationDtoScreen(for type: ApiType) -> UIControllerSharedScreen {
    switch type {
    case .authentication(.login):
        return UIControllerScreenConfiguration(for: type, title: "Login")
    case .authentication(.logout):
        return UIControllerScreenConfiguration(for: type, title: "Logout")
    default:
        fatalError("Unsupported API type")
    }
}

方案3:修改原始值(若业务允许)

如果服务器端可以配合调整,直接给登录、登出设置不同的原始值,这是最直接的解决方式:

enum ApiType: String, CaseIterable {
    case dashboard = "dashboardRootIdApi"
    case profile = "profileRootIdApi"
    case usemeInLogin = "authenticationLoginApi"
    case usemeInLogout = "authenticationLogoutApi"
}

此时你的原有switch分支可以正常触发。

方案4:添加枚举属性区分(局限性大)

若无法修改枚举结构,可给每个case添加场景属性,但仅适用于直接通过case创建枚举值的场景(从rawValue初始化仍会优先匹配第一个case):

enum ApiType: String, CaseIterable {
    case dashboard = "dashboardRootIdApi"
    case profile = "profileRootIdApi"
    case usemeInLogin = "authenticationAccessIdApi"
    case usemeInLogout = "authenticationAccessIdApi"
    
    var businessScene: String {
        switch self {
        case .usemeInLogin: return "login"
        case .usemeInLogout: return "logout"
        default: return self.rawValue
        }
    }
}

内容的提问来源于stack exchange,提问作者User Unknown

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 17:30:54