【问题标题】:Get Swift enum type from string that matches type, not rawValue从匹配类型的字符串中获取 Swift 枚举类型,而不是 rawValue
【发布时间】:2020-11-12 12:13:32
【问题描述】:

我正在使用一个第三方库,该库有一个定义了一些媒体设备类型的枚举类。我还有一个 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”

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

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
    }
  }

下一个方法有两个参数,一个String,和一个可选的MediaDeviceType。如果第二个参数不匹配,则该方法切换init 方法。 Documentation.

我的基本实现:

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

我是非常 Swift 新手,所以也许我在这里缺少一些明显的东西?

【问题讨论】:

  • “当传递给下一个方法时它实际上并没有按预期工作”是什么意思?你能提供一个minimal reproducible example吗?
  • 你真的在使用 Swift3 吗?如果是这样,为什么? Swift 5.3 是最新版本。
  • @DávidPásztor 抱歉,我一定是不小心点击了那个
  • @Sweeper 添加了我的基本实现
  • hopefullyEnumType 是可选的。您需要先解包,然后才能将其传递给init,这需要一个非可选参数。

标签: swift enums


【解决方案1】:

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

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
    }
}

【讨论】:

  • 这实际上与我最终做的事情非常相似,谢谢!问题实际上与枚举无关,而是与将特定 MediaDevice 存储在内存中的第三方 SDK 有关,但这没有记录在案。创建新的 MediaDevice 无效。令人沮丧,打算在他们的 GitHub 上发布一个关于它的问题。
【解决方案2】:

快速代码是:

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

init(from string: String) {
    switch (string) {
        case "audioBluetooth":
            self = .audioBluetooth
        case "audioWiredHeadset":
            self = .audioWiredHeadset
        case "audioBuiltInSpeaker":
            self = .audioBuiltInSpeaker
        case "audioHandset":
            self = .audioHandset
        case "videoFrontCamera":
            self = .videoFrontCamera
        case "videoBackCamera":
            self = .videoBackCamera
        default:
            self = .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"
    }
}
}

【讨论】:

  • 很遗憾我无法更新第三方 SDK 代码
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-08
  • 2017-01-14
  • 2018-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-23
相关资源
最近更新 更多