【问题标题】:Enum class in swiftswift中的枚举类
【发布时间】:2016-08-11 11:00:42
【问题描述】:

我正在尝试创建一个具有类型和返回所有类型的函数的枚举类。

最初我的对象类中有我的枚举和一个将这些作为数组返回的函数:

class someClass: Mappable {

enum Type: Int {
    case A = 0
    case B = 1
    case C = 2
        }
    }
}

func getAllTypes() -> [Type] {
    return [Type.A, Type.B, Type.C]
}
}

我想从我的对象类中提取它的原因是因为这种类型也用于其他类,我不想复制任何不必要的代码。

我可以设法对枚举进行子类化,但不能对返回数组中所有类型的函数进行子类化。

任何帮助将不胜感激。

【问题讨论】:

  • 您可能需要重命名您的enum,因为Type 是为Swift class 中的其他内容保留的;并且类名也应该大写,例如SomeClass

标签: ios swift class object enums


【解决方案1】:

使用只执行一次的闭包和AnyGenerator初始化all

@vacawama 展示了如何使用只执行一次的闭包结合enum 的可失败init(rawValue:) 初始值来以通用方式初始化all 数组。前面提到的答案中方法的一个细微变化是交换显式的while 循环和附加AnyGenerator 的数组:

enum Type: Int {
    case A = 0, B, C, D, E, F, G, H

    static let all: [Type] = {
        var rValue = 0
        return AnyGenerator<Type> {
            defer { rValue += 1 }
            return Type(rawValue: rValue)
        }.map{$0}
    }()
}

print(Type.all) 
    // [Type.A, Type.B, Type.C, Type.D, Type.E, Type.F, Type.G, Type.H]

这在 rawValue 只是 ++ 增加 (0, 1, 2, ...) 的条件下有效。


通过使enum符合SequenceType来初始化all

作为另一种选择,由于您的 rawValue 是整数顺序的 (++),您可以让您的 enum 符合 SequenceType,在这种情况下,可以轻松生成所有案例的数组只需使用.map

enum Type: Int, SequenceType {
    case A = 0, B, C, D, E, F, G, H
    
    init() { self = A } // Default (first) case intializer
    
    /* conform Type to SequenceType (here: enables only 
       simple (self.rawValue)...last traversing) */
    func generate() -> AnyGenerator<Type> {
        var rValue = self.rawValue
        return AnyGenerator {
            defer { rValue += 1 }
            return Type(rawValue: rValue)
        }
    }
    
    /* use the fact that Type conforms to SequenceType to neatly
     initialize your static all array */
     static let all = Type().map { $0 }
}

print(Type.all) 
    // [Type.A, Type.B, Type.C, Type.D, Type.E, Type.F, Type.G, Type.H]

应用此一致性来初始化静态 all 数组可能有点矫枉过正,但如果您希望能够使用 enum 的其他方面,这是一个可行的替代方案符合SequenceType

for typeCase in Type() {
    // treat each type ...
    print(typeCase, terminator: " ")
} // A B C D E F G H

for caseFromEAndForward in Type.E {
    print(caseFromEAndForward, terminator: " ")
} // E F G H

使用flatMap根据rawValue的范围初始化案例

最后,作为@appzYourLife neat solution的变体,如果你有很多情况,你可以在rawValue的范围内使用flatMap操作来初始化静态allValues数组,例如

enum Type: Int {
    case A = 0, B, C, D, E, F, G, H
    static let all = (A.rawValue...H.rawValue)
       .flatMap{ Type(rawValue: $0) }
}

print(Type.all) 
    // [Type.A, Type.B, Type.C, Type.D, Type.E, Type.F, Type.G, Type.H]

然而,这种方法实际上并没有任何实际用途,因为一般大小方法(@vacawama:s 或上面的SequenceType)对于许多情况下的枚举总是更可取的。我可以看到的可能用例是不同情况下的rawValue 是否是连续的但不仅仅是++,例如如果rawValue 用于某些位掩码

// ...
case A = 0, B = 2, C = 4, D = 8, E = 16, F = 32, G = 64, H = 128

上述方法将使用暴力破解rawValue 的范围,其中少数实际上对应于实际情况。有点浪费,但由于它是一次性静态初始化,这应该不是问题。

【讨论】:

  • 不错的解决方案。我将var 更改为let,因为all 数组在编译后不会更改。我希望有一天 Swift 会提供一种自动方法来将所有值检索到一个枚举中。
  • @appzYourLife 啊是的,也会在这里更新,谢谢!在这种情况下,我相信在您的解决方案中使用显式案例会更好(因为无论如何我们在上面的定义中都有它们:)),但是 if 我们可以检索原始值范围枚举,那么flatMap 解决方案可能更有用(或者,在另一种情况下:也许如果我们需要在枚举定义之外的外部函数中使用它)。
  • @dfri 您的解决方案也是可行的。谢谢。尽管我使用了上面的,因为我没有很多类型:)
  • 在您的 flapMap 示例中,您可以使用范围 (A.rawValue...H.rawValue) 来消除幻数。
【解决方案2】:

为什么不简单地为枚举类型添加一个静态属性?

enum Type: Int {
    case A = 0, B, C
    static let all = [A, B, C]
}

【讨论】:

  • 由于在enum 定义中,您可以在数组中的所有情况下省略.(即... = [A, B, C])。
  • 这是我用过的。谢谢@appzYourLife
【解决方案3】:

如果您的rawValues 是连续的Ints,您可以利用Type(rawValue:) 初始化程序将失败并返回nil 的非法值来自动计算Type.all 而无需显式列出值或设置范围。如果您在枚举中添加更多案例,它将自动调整:

enum Type: Int {
    case A, B, C, D, E, F, G, H, I, J, K
    static let all: [Type] = {
        var all: [Type] = []
        var value = 0
        while let e = Type(rawValue: value) {
            all.append(e)
            value += 1
        }
        return all
    }()
}

print(Type.all)
[Type.A, Type.B, Type.C, Type.D, Type.E, Type.F, Type.G, Type.H, Type.I, Type.J, Type.K]

【讨论】:

  • 整洁!可能值得指出(对于该线程的未来读者),这(以及我自己的解决方案)在 rawValue:s 只是 ++ 顺序的条件下工作(例如,没有位掩码 1, 2, 4, ... 或类似的 rawValues) .
  • 我不会将其包含在我自己的答案中,因为巧妙地使用只执行一次的闭包是此答案的想法,但请注意,您也可以在这里使用make use of AnyGenerator (可能) 稍微更简洁的版本。
  • @dfri,继续使用只执行一次的闭包来回答你的问题。目标是产生最佳答案,并且经常迭代其他人的答案会产生更好的答案。
【解决方案4】:

你可以定义一个包含所有可能的枚举值的静态数组:

static let allValues = [A, B, C]

然后你可以在你想要的地方使用它:

var allEnumValues = Type.allValues

【讨论】:

    【解决方案5】:

    斯威夫特 5

    现在你有CaseIterableApple docsAnother topic.

    符合 CaseIterable 协议的类型通常是 没有关联值的枚举。使用 CaseIterable 时 类型,您可以通过使用访问所有类型案例的集合 类型的 allCases 属性。

    enum Direction: CaseIterable {
      case left
      case right
      case up
      case down
    }
    
    Direction.allCases.count
    Direction.allCases.forEach { print($0) }
    

    【讨论】:

      【解决方案6】:

      如果它也用于其他类,那么不要将它放在一个类中

      class YourClass : Mappable {
      
      }
      
      enum Type: Int {
          case A = 0
          case B = 1
          case C = 2
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2020-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-26
        相关资源
        最近更新 更多