当前位置: 首页 > 知识库问答 >
问题:

在Swift 3.0中遍历枚举

澹台胜
2023-03-14

我有一个简单的枚举,我想迭代一下。为此,我采用了顺序和迭代器协议,如下面的代码所示。顺便说一句,这可以复制/粘贴到Xcode 8中的游乐场。

import UIKit

enum Sections: Int {
  case Section0 = 0
  case Section1
  case Section2
}

extension Sections : Sequence {
  func makeIterator() -> SectionsGenerator {
    return SectionsGenerator()
  }

  struct SectionsGenerator: IteratorProtocol {
    var currentSection = 0

    mutating func next() -> Sections? {
      guard let item = Sections(rawValue:currentSection) else {
        return nil
      }
      currentSection += 1
      return item
    }
  }
}

for section in Sections {
  print(section)
}

但是for in循环生成错误消息“Type”节。Type不符合协议“Sequence”。协议一致性在我的扩展中;那么,这个代码有什么问题?

我知道还有其他方法可以做到这一点,但我想知道这种方法有什么问题。

谢谢

共有3个答案

喻增
2023-03-14

简单地添加到枚举:静态var allType:[Sections] = [. Section0,. Section1,. Section2]

然后你可以:

Sections.allTypes.forEach { (section) in
            print("\(section)")
}
徐昕
2023-03-14

更新:从Swift 4.2开始,您只需将协议一致性添加到caseitrable,请参阅如何使用字符串类型枚举枚举?。

您可以迭代符合序列协议的类型的值。因此

for section in Sections.Section0 {
  print(section)
}

会编译并给出预期的结果。但是当然这不是你真正想要的,因为值的选择是任意的,值本身在序列中是不需要的。

据我所知,没有办法迭代一个类型本身,所以

for section in Sections {
  print(section)
}

编译。这就需要“元类型”部分。类型符合序列。也许有人证明我错了。

您可以定义一个返回序列的类型方法:

extension Sections {
    static func all() -> AnySequence<Sections> {
        return AnySequence {
            return SectionsGenerator()
        }
    }

    struct SectionsGenerator: IteratorProtocol {
        var currentSection = 0

        mutating func next() -> Sections? {
            guard let item = Sections(rawValue:currentSection) else {
                return nil
            }
            currentSection += 1
            return item
        }
    }

}

for section in Sections.all() {
    print(section)
}
薛弘厚
2023-03-14

请注意,Martin的解决方案可以重构为协议:

import Foundation

protocol EnumSequence
{
    associatedtype T: RawRepresentable where T.RawValue == Int
    static func all() -> AnySequence<T>
}
extension EnumSequence
{
    static func all() -> AnySequence<T> {
        return AnySequence { return EnumGenerator() }
    }
}

private struct EnumGenerator<T: RawRepresentable>: IteratorProtocol where T.RawValue == Int {
    var index = 0
    mutating func next() -> T? {
        guard let item = T(rawValue: index) else {
            return nil
        }
        index += 1
        return item
    }
}

然后,给出一个枚举

enum Fruits: Int {
    case apple, orange, pear
}

你拍打协议和类型:

enum Fruits: Int, EnumSequence {
    typealias T = Fruits
    case apple, orange, pear
}

Fruits.all().forEach({ print($0) }) // apple orange pear
 类似资料:
  • 我的Flutter项目中有一个Dart枚举,如下所示: 如果我有一些随机枚举状态,如,我如何迭代到下一个枚举(而不需要做一些事情,如用开关语句映射它们)? 我在这个,这个和这个的帮助下找到了答案,所以我把它贴在下面。

  • 运行此代码时: 引发异常: 系统。无效操作异常:集合被修改;枚举操作可能无法执行。 怎么做。NET知道该集合在枚举器迭代该集合时被修改了吗?集合对象中是否有此标志?

  • 我有一个列表,我想知道它是否包含除枚举类中的元素以外的任何其他元素。 我有这个工作: 这是可行的,但是我如何用流替换for循环,并且使它在更少的行中呢?

  • 问题内容: 我有一个如下的JavaScript对象: 现在我想通过所有回路元素(,,…),并得到他们的键和值。我怎样才能做到这一点? 我可以根据需要修改JavaScript对象。我的最终目标是遍历一些键值对,如果可能的话,我想避免使用。 问题答案: 您可以使用其他人所示的循环。但是,您还必须确保获得的键是对象的实际属性,而不是来自原型。 这是代码段: 用Object.keys()替代: 请注意,使

  • 问题内容: 我有以下代码: 打印出以下内容: {“ active”:{“ label”:“ Active”,“ value”:“ 12”},“ automatic”:{“ label”:“ Automatic”,“ value”:“ 8”},“ waiting”:{ “ label”:“正在等待”,“ value”:“ 1”},“ manual”:{“ label”:“ Manual”,“ val

  • 问题内容: 我在下面的EJS中有代码, 行的输出是正确的,由3个对象组成的数组,每个对象具有属性ID,名称等。我可以操纵行以在JS中填充表格。但是,我想知道是否有一种方法可以通过上述方式完成? 当我运行上面的代码时,JSON.stringify(data).length不是3,而是整个字符串的长度。 另一个问题是当我尝试添加 <%警报(’t’); %>或<%window.alert(’t’); %