从匹配类型的字符串中获取 Swift 枚举类型,而不是 rawValue
Posted
技术标签:
【中文标题】从匹配类型的字符串中获取 Swift 枚举类型,而不是 rawValue【英文标题】:Get Swift enum type from string that matches type, not 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"
我尝试过的事情:
如您所见,.rawValue
是 Int
,这意味着我无法使用枚举的初始化程序访问该值:
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
,这需要一个非可选参数。
【参考方案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 代码以上是关于从匹配类型的字符串中获取 Swift 枚举类型,而不是 rawValue的主要内容,如果未能解决你的问题,请参考以下文章