代码之家  ›  专栏  ›  技术社区  ›  androidguy

在Swift运行时,我是否可以从枚举名和值的rawValue实例化或生成枚举值?

  •  1
  • androidguy  · 技术社区  · 4 年前

    EnumSet (两个功能一起工作):

    fun <EnumT : Enum<EnumT>> ConvertStrToEnum(enumClass: Class<EnumT>, str: String?): EnumT? {
        if (str == null)
            return null
        for (enumval in enumClass.enumConstants) {
            if (enumval.toString() == str)
                return enumval
        }
        throw IllegalArgumentException("Gave an invalid enum value for class ${enumClass.canonicalName}: [$str]")
    }
    
    fun <EnumT : Enum<EnumT> > ConvertStrArrayToEnumSet(enumClass: Class<EnumT>, array: List<String>?) : EnumSet<EnumT> {
        val set = EnumSet.noneOf(enumClass)
        array?.forEach { value -> ignoreExceptions { set.add(ConvertStrToEnum(enumClass, value)) } }
        return set
    }
    

    更清楚的是,实际用法是:

    var intent: EnumSet<Intent>
    intent = ConvertStrArrayToEnumSet(Intent::class.java, filters.array(MatchFilter.Intent.jsonName))
    

      public var intents: Set<Intent>
      if let jsonIntents = filters?["intent"] as? Array<String> {
         for jsonIntent in jsonIntents {
            if let intent = Intent(rawValue: jsonIntent) {
               intents.insert(intent)
            }
         }
      }
    
    1 回复  |  直到 4 年前
        1
  •  1
  •   Sweeper    4 年前

    假设你的枚举是 RawRepresentable RawValue == String ...

    Swift中的枚举没有特殊的“基类”,比如 Enum . 但在这种情况下,我们真的只需要利用他们的共同财产-两者 可表示的 Hashable 任何 符合这两个协议的类型。很不错吧?

    func convertStringArrayToEnumSet<T>(type: T.Type, _ strings: [String]) -> Set<T> 
        where T : RawRepresentable & Hashable, T.RawValue == String {
        Set(strings.compactMap(T.init(rawValue:)))
    }
    

    注意使用 compactMap

    func convertRawValueArrayToEnumSet<T>(type: T.Type, _ rawValues: [T.RawValue]) -> Set<T> 
        where T : RawRepresentable & Hashable {
        Set(rawValues.compactMap(T.init(rawValue:)))
    }
    
        2
  •  0
  •   Jessy    4 年前

    Sweeper的回答是好的,但是我看到你在错误处理上付出了一些努力。斯威夫特不擅长帮助你,所以你必须自己扩展。

    ( Dictionary RawRepresentable 来自Swift 1,没有错误。他们从来没有现代化,只是返回可选。)

    /// Acts as a dictionary that `throw`s instead of returning optionals.
    public protocol valueForKeyThrowingAccessor {
      associatedtype Key
    
      /// Should just be a throwing subscript, but those don't exist yet.
      func value<Value>(for: Key) throws -> Value
    }
    
    /// Acts as a dictionary.
    public protocol valueForKeySubscript: valueForKeyThrowingAccessor {
      associatedtype Value
    
      subscript(key: Key) -> Value? { get }
    }
    
    public extension valueForKeySubscript {
      /// - Throws: `KeyValuePairs<Key, Value>.AccessError.noValue`
      func value(for key: Key) throws -> Value {
        guard let value = self[key]
        else { throw KeyValuePairs<Key, Value>.AccessError.noValue(key: key) }
    
        return value
      }
    
      /// - Throws: `KeyValuePairs<Key, Value>.AccessError.typeCastFailure`
      func value<Value>(for key: Key) throws -> Value {
        guard let value = try value(for: key) as? Value
        else { throw KeyValuePairs<Key, Value>.AccessError.typeCastFailure(key: key) }
    
        return value
      }
    }
    
    extension Dictionary: valueForKeySubscript { }
    
    public extension KeyValuePairs {
      /// An error throw from trying to access a value for a key.
      enum AccessError: Error {
        case noValue(key: Key)
        case typeCastFailure(key: Key)
      }
    }
    
    public extension RawRepresentable {
      /// Like `init(rawValue:)`, if it was throwing instead of failable.
      /// - Throws: `RawRepresentableExtensions<Self>.Error.invalidRawValue`
      /// if there is no value of the type that corresponds with the specified raw value.
      init(_ rawValue: RawValue) throws {
        guard let instance = Self(rawValue: rawValue)
        else { throw RawRepresentableExtensions<Self>.Error.invalidRawValue(rawValue) }
    
        self = instance
      }
    }
    
    /// A namespace for nested types within `RawRepresentable`.
    public enum RawRepresentableExtensions<RawRepresentable: Swift.RawRepresentable> {
      public enum Error: Swift.Error {
        case invalidRawValue(RawRepresentable.RawValue)
      }
    }
    
    public extension InitializableWithElementSequence where Element: RawRepresentable {
      /// - Throws: `RawRepresentableExtensions<Element>.Error.invalidRawValue`
      init<RawValues: Sequence>(rawValues: RawValues) throws
      where RawValues.Element == Element.RawValue {
        self.init(
          try rawValues.map(Element.init)
        )
      }
    }
    
    /// A type that can be initialized with a `Sequence` of its `Element`s.
    public protocol InitializableWithElementSequence: Sequence {
      init<Sequence: Swift.Sequence>(_: Sequence)
      where Sequence.Element == Element
    }
    
    extension Array: InitializableWithElementSequence { }
    extension Set: InitializableWithElementSequence { }
    
    extension InitializableWithElementSequence where Element == Intent {
      init(filters: [String: Any]) throws {
        try self.init(
          rawValues: try filters.value(for: "intent") as [String]
        )
      }
    }
    
    try filters.map(Set.init)