首页 > 解决方案 > 从匹配类型的字符串中获取 Swift 枚举类型,而不是 rawValue

问题描述

我正在使用一个第三方库,它有一个定义一些媒体设备类型的枚举类。我还有一个 API,可以将媒体设备类型作为字符串提供给 Swift 代码。我需要以某种方式该字符串中获取媒体设备类型,以便可以将其传递给另一个方法。

第三方枚举

@objc public enum MediaDeviceType: Int, CustomStringConvertible {
    case audioBluetooth
    case audioWiredHeadset
    case audioBuiltInSpeaker
    case audioHandset
    case videoFrontCamera
    case videoBackCamera
    case other

    public var description: String {
        switch self {
        case .audioBluetooth:
            return "audioBluetooth"
        case .audioWiredHeadset:
            return "audioWiredHeadset"
        case .audioBuiltInSpeaker:
            return "audioBuiltInSpeaker"
        case .audioHandset:
            return "audioHandset"
        case .videoFrontCamera:
            return "videoFrontCamera"
        case .videoBackCamera:
            return "videoBackCamera"
        case .other:
            return "other"
        }
    }
}

我尝试过的事情:

如您所见,.rawValueInt意味着我无法使用枚举的初始化程序访问该值:

let stringType = "audioBluetooth"
let type = MediaDeviceType(rawValue: stringType)

这给了我错误:

无法将“String”类型的值转换为预期的参数类型“Int”

我想也许我可以返回正确switchstringType媒体设备类型,但似乎在传递给下一个方法时它实际上并没有按预期工作。

private func getMediaTypeStringToEnum(type: String) -> MediaDeviceType? {
    switch (type) {
    case "audioBluetooth":
      return .audioBluetooth
    case "audioWiredHeadset":
      return .audioWiredHeadset
    case "audioBuiltInSpeaker":
      return .audioBuiltInSpeaker
    case "audioHandset":
      return .audioHandset
    case "videoFrontCamera":
      return .videoFrontCamera
    case "videoBackCamera":
      return .videoBackCamera
    case "other":
      return .other
    default:
      return nil
    }
  }

下一个方法采用两个参数 aString和一个可选的 MediaDeviceType。如果第二个参数不匹配,则方法切换init方法。文档

我的基本实现:

let stringType = "audioBluetooth"
let label = "Media Device Label"
let hopefullyEnumType = getMediaTypeStringToEnum(stringType)
let mediaDevice = MediaDevice(label, hopefullyEnumType)

我对 Swift陌生,所以也许我在这里遗漏了一些明显的东西?

标签: swiftenums

解决方案


如果您绝对确定将来不会使用新案例扩展枚举案例,那么一种解决方案是遍历所有案例并查看哪些匹配:

private func getMediaTypeStringToEnum(type: String) -> MediaDeviceType? {
    let allMediaTypes: [MediaDeviceType] = [.audioBluetooth, .audioWiredHeadset, .audioBuiltInSpeaker, .audioHandset, .videoFrontCamera, .videoBackCamera, .other]
    return allMediaTypes.first { $0.description == type }
}

如果您不确定,那么您必须密切关注枚举声明,并在allMediaTypes发生这种情况时将新案例添加到数组中。

当然,如果枚举是CaseIterable,那么您的问题将不太容易解决,并且不需要维护代码:

private func getMediaTypeStringToEnum(type: String) -> MediaDeviceType? {
    MediaDeviceType.allCases.first { $0.description == type }
}

作为旁注,您还可以在枚举上实现一个可失败的初始化程序,这应该使解决方案更易于使用,并且与枚举更具凝聚力:

extension MediaDeviceType {
    init?(string: String) {
        // do your thing
    }
}

推荐阅读