【问题标题】:Creating collection of different enums创建不同枚举的集合
【发布时间】:2016-07-05 08:30:50
【问题描述】:

是否可以创建不同枚举类型的数组?

例如:

MyEnums.swift:

class MyEnums {
    enum FirstEnum: String {
        case Type1, Type2, Type3
    }

    enum SecondEnum: String {
        case Type1, Type2, Type3
    }
}

IteratorManager.swift:

class IteratorManager {
    var enumsArray = [MyEnums]()

    func iterate() {
        for e in enumsArray {
            print(e.rawValue)
        }
    }
}

我尝试了许多解决方案 - 扩展、协议、在结构或枚举中的类中分组(如上面的示例) - 但没有任何效果。

【问题讨论】:

  • 您能否提供一个示例,说明您尝试实现的什么,而不是如何 尝试实现这一目标?至于最初的问题,我相信有一个使用协议的简单解决方案。只需为两种枚举类型声明 MyProtocol 并使用 Array
  • 枚举是在编译时创建的静态顶级对象(如类和结构)。如果不添加包含成员的显式数组,则无法遍历枚举的成员。一个例外是具有 Int 类型的枚举,以 0 和连续值开头。这个枚举可以通过索引进行迭代。

标签: arrays swift loops enums nested


【解决方案1】:

是的,但你应该知道你是怎么做的。

枚举创建一个具体的类型。 Swift 是类型安全的语言。 FirstEnum 数组不允许包含非 FirstEnum 类型的项目。

但是,有两种方法可以实现这一点。 1。救援协议 2。输入谎言

我会同时使用这两种方法,但我绝不会推荐使用第二种方法,尽管它似乎很简单且难以捉摸。

我将从第二个开始。

enum FirstEnum: String {
    case Type1, Type2, Type3
}

enum SecondEnum: String {
    case Type1, Type2, Type3
}

让我们创建一些具体类型的枚举。

let firstEnum1 = FirstEnum.Type1
let firstEnum2 = FirstEnum.Type2
let secondEnum1 = SecondEnum.Type3

让我们使用第二个选项来打包它们:

let a:[Any] = [firstEnum1, firstEnum2, secondEnum1] //works

让我们看看我们以后如何提取它:

for index in a {
 if let a = index as? FirstEnum {  //This is bad
    print(a.rawValue)
 }

 if let a = index as? SecondEnum { //Aweful
    print(a.rawValue)
 }
}

看到我们必须将其转换回我们插入的内容。我们必须使用期望,谁知道我们得到的可能是字符串而不是枚举。因为 Any 可以按字面意思表示 Any。

让我们看看如何通过第一个选项解决这个问题:

let b:[RawRepresentable] = [firstEnum1, secondEnum1]  //Cant do so because of Associated Type

那段代码不起作用,因为它 RawRepresentable 是一个不完整的类型。所以我们需要定义自己的协议。

protocol CustomStringRepresentableEnum {
   var rawValue: String { get }
}

那么我们的枚举当然支持 rawValue,因此我们可以追溯地对该协议进行建模。

 extension FirstEnum: CustomStringRepresentableEnum { }
 extension SecondEnum: CustomStringRepresentableEnum { }

现在我们可以创建一个具体已知类型的数组。

let b:[CustomStringRepresentableEnum] = [firstEnum1, firstEnum2, secondEnum1]

这很好,因为除了符合协议的内容之外,我们不允许输入任何内容。这是正确类型和约束的,编译器将帮助您防止发生诸如错误转换之类的坏事。

让我们用它来证明我们写了一些好的代码。

for index in b {
    print(index.rawValue)
}

原来如此。您可以在一个数组中有不同的枚举,但不知何故,它们需要是同质的。您可以用 Any 欺骗编译器并编写丑陋的代码或使用协议和泛型来编写有效的和健壮的代码。选择是你的。

【讨论】:

    【解决方案2】:

    @kandelvijaya感谢您提供全面而全面的答案。

    到目前为止,我已经形成了一些其他的态度,它基于带有属性的枚举初始化:

    MyEnums.swift:

    enum MyEnums {
        enum FirstEnum: String {
            case Type1, Type2, Type3
        }
    
        enum SecondEnum: String {
            case Type1, Type2, Type3
        }
    
        case First(FirstEnum)
        case Second(SecondEnum)
    
        var rawValue: String {
            switch self {
            case .First(let e):
                return e.rawValue
            case .Second(let e):
                return e.rawValue
            }
        }
    }
    

    IteratorManager.swift:

    class IteratorManager {
        var enumsArray = [MyEnums]()
    
        func iterate() {
            for e in enumsArray {
                print(e.rawValue)
            }
        }
    }
    

    填充数组和迭代:

    let iteratorManager = IteratorManager()
    iteratorManager.enumsArray = [MyEnums.First(MyEnums.FirstEnum.Type1), MyEnums.Second(MyEnums.SecondEnum.Type2)]
    iteratorManager.iterate()
    

    它也是类型安全的(不像 Any 的解决方案)。

    此外,我们可以定义一个示例协议:

    protocol MyEnumsProtocol {
        var processedValue: String { get }
        static func typeGeneralDescription() -> String
    }
    

    实现它:

    enum MyEnums {
        enum FirstEnum: String, MyEnumsProtocol {
            case Type1, Type2, Type3
    
            var processedValue: String {
                return "-=\(self)-="
            }
    
            static func typeGeneralDescription() -> String {
                return "First enum type"
            }
        }
    
        enum SecondEnum: String, MyEnumsProtocol {
            case Type1, Type2, Type3
    
            var processedValue: String {
                return "-=\(self)-="
            }
    
            static func typeGeneralDescription() -> String {
                return "Second enum type"
            }
        }
    
        case First(FirstEnum)
        case Second(SecondEnum)
    
        var rawValue: String {
            switch self {
            case .First(let e):
                return e.rawValue
            case .Second(let e):
                return e.rawValue
            }
        }
    
        var subTypeDesc: String {
            switch self {
            case .First(let e):
                return "\(FirstEnum.typeGeneralDescription()): \(e.processedValue)"
            case .Second(let e):
                return "\(SecondEnum.typeGeneralDescription()): \(e.processedValue)"
            }
        }
    }
    

    并像这样使用它:

    let subTypeDesc = iteratorManager.enumsArray.first?.subTypeDesc
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-10
      • 2015-10-14
      • 2013-01-25
      • 2011-04-09
      相关资源
      最近更新 更多