Pha*_*m59 5 enums enumeration sequence swift
我有一个简单的枚举,我想迭代.为此,我采用了Sequence和IteratorProtocol,如下面的代码所示.顺便说一句,这可以复制/粘贴到Xcode 8中的Playground.
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)
}
Run Code Online (Sandbox Code Playgroud)
但是for-in循环生成错误消息"Type'Sections.Type'不符合协议'Sequence'".协议一致性在我的扩展中; 那么,这段代码有什么问题?
我知道还有其他方法可以做到这一点,但我想了解这种方法有什么问题.
谢谢.
Jan*_*ano 10
请注意,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
}
}
Run Code Online (Sandbox Code Playgroud)
然后,给出一个枚举
enum Fruits: Int {
case apple, orange, pear
}
Run Code Online (Sandbox Code Playgroud)
你打了协议和一个typealias:
enum Fruits: Int, EnumSequence {
typealias T = Fruits
case apple, orange, pear
}
Fruits.all().forEach({ print($0) }) // apple orange pear
Run Code Online (Sandbox Code Playgroud)
更新:从Swift 4.2开始,您可以简单地添加协议一致性CaseIterable,请参阅如何使用String类型枚举枚举?.
您可以迭代符合
协议的类型的值Sequence.因此
for section in Sections.Section0 {
print(section)
}
Run Code Online (Sandbox Code Playgroud)
会编译并给出预期的结果.但是当然这并不是你想要的,因为值的选择是任意的,序列中不需要值本身.
据我所知,没有办法迭代一个类型本身,所以
for section in Sections {
print(section)
}
Run Code Online (Sandbox Code Playgroud)
编译.这将要求"元变型" Sections.Type符合Sequence.也许有人证明我错了.
你可以做的是定义一个返回序列的类型方法:
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)
}
Run Code Online (Sandbox Code Playgroud)
只需添加到枚举:
static var allTypes: [Sections] = [.Section0, .Section1, .Section2]
而且你可以:
Sections.allTypes.forEach { (section) in
print("\(section)")
}
Run Code Online (Sandbox Code Playgroud)