其实所有的内容均来自Apple开发官网
IteratorProtocol
类型:Protocol
说明:一次提供一个序列值的类型。
申明
protocol IteratorProtocol
概述
迭代器协议与序列协议紧密相连。序列通过创建一个迭代器来提供对其元素的访问,迭代器跟踪其迭代过程,并在一次返回一个元素。
无论何时在数组、集合或任何其他集合或序列使用for-in,都将使用该类型的迭代器。Swift在内部使用序列或集合的迭代器来启用for-in循环。
使用序列的迭代器可以直接访问相同的元素,访问顺序与使用for in循环在序列上迭代相同。例如,您通常可以使用For-in循环来打印数组中的每个元素。
let animals = ["Antelope", "Butterfly", "Camel", "Dolphin"]
for animal in animals {
print(animal)
}
// Prints "Antelope"
// Prints "Butterfly"
// Prints "Camel"
// Prints "Dolphin"
在幕后,Swift使用动物数组的迭代器循环遍历数组的内容。
var animalIterator = animals.makeIterator()
while let animal = animalIterator.next() {
print(animal)
}
// Prints "Antelope"
// Prints "Butterfly"
// Prints "Camel"
// Prints "Dolphin"
对anims.makeIterator()的调用返回数组迭代器的一个实例。接下来,while循环重复调用迭代器的Next()方法,绑定返回给animal的每个元素,并在Next()方法返回nil时退出
直接使用迭代器
很少需要直接使用迭代器,因为for-in循环是在Swift中遍历序列的更惯用方法。然而,有些算法可能需要直接使用迭代器。
一个例子是reduce1(:)方法。与在标准库中定义的reduce(::)方法(接受初始值和组合闭包)类似,reduce1(:)使用序列的第一个元素作为初始值。
下面是reduce1(_:)方法的一个实现。序列的迭代器直接用于在循环遍历序列的其余部分之前检索初始值。
extension Sequence {
func reduce1(
_ nextPartialResult: (Element, Element) -> Element
) -> Element?
{
var i = makeIterator()
guard var accumulated = i.next() else {
return nil
}
while let element = i.next() {
accumulated = nextPartialResult(accumulated, element)
}
return accumulated
}
}
reduce1(_:)方法使某些类型的序列操作更简单。以下是如何使用前面介绍的动物数组作为示例来查找序列中最长的字符串:
let longestAnimal = animals.reduce1 { current, element in
if current.count > element.count {
return current
} else {
return element
}
}
print(longestAnimal)
// Prints "Butterfly
使用多个迭代器
每当您在一个序列上使用多个迭代器(或for in loops)时,请确保您知道特定序列支持重复迭代,这可能是因为您知道它的具体类型,也可能是因为序列还受集合协议的约束。
从对序列的makeIterator()方法的单独调用中获取每个独立的迭代器,而不是通过复制。复制迭代器是安全的,但是通过调用迭代器的next()方法来推进迭代器的一个副本可能会使该迭代器的其他副本失效。而for-in loops是安全的在这钟条件下。
向类型添加迭代器协议一致性
实现一个符合IteratorProtocol的迭代器很简单。声明一个next()方法,该方法在相关序列中前进一步并返回当前元素。当序列用完时,next()方法返回nil。
例如,考虑一个自定义的倒计时序列。您可以使用起始整数初始化倒计时序列,然后循环倒计时到零。倒计时结构的定义很短:它只包含序列协议所需的起始计数和makeIterator()方法。
struct Countdown: Sequence {
let start: Int
func makeIterator() -> CountdownIterator {
return CountdownIterator(self)
}
}
makeIterator()方法返回另一个自定义类型,一个名为CountdownIterator的迭代器。CountdownIterator类型跟踪它正在迭代的倒计时序列和返回值的次数。
struct CountdownIterator: IteratorProtocol {
let countdown: Countdown
var times = 0
init(_ countdown: Countdown) {
self.countdown = countdown
}
mutating func next() -> Int? {
let nextNumber = countdown.start - times
guard nextNumber > 0
else { return nil }
times += 1
return nextNumber
}
}
每次对CountdownIterator实例调用next()方法时,它都会计算新的next值,检查是否已达到零,然后返回数字,如果iterator已完成返回序列元素,则返回nil。
在倒计时序列上创建和迭代使用倒计时迭代器来处理迭代。
let threeTwoOne = Countdown(start: 3)
for count in threeTwoOne {
print("\(count)...")
}
// Prints "3..."
// Prints "2..."
// Prints "1..."
Topics
关联类型
associatedtype Element
// The type of element traversed by the iterator.
// Required.
实例方法
func next() -> Self.Element?
// Advances to the next element and returns it, or nil if no next element exists.
// Required.