里面只有一个方法next( )
public protocol IteratorProtocol {
///迭代器产生的值的类型
///如 subViews的迭代原生类型就是View 可以不用写,编译器根据next()的返回值自动判断。
associatedtype Element
///你只需要在每次调用的时候返回下一个值,结束时返回nil
public mutating func next() -> Self.Element?
}
next( )方法是用 mutating
关键字修饰。 几乎所有的迭代器都要求是可变状态
,可以用于改变结构体中记录迭代器位置的变量值(如下面demo中的startNum)
下面我们用迭代器写一个斐波那契数列(0,1,1,2,3,5,8,13.....)。
struct FibsNumIterator:IteratorProtocol {
var startNum = (0, 1)
mutating func next() -> Int? {
let nextNum = startNum.0
startNum = (startNum.1, startNum.0 + startNum.1)
return nextNum
}
}
这个迭代器不返回nil, 就会产生无穷的数组。 程序会因为类型溢出而crash。
注:迭代器是单向结构
,只能按照增加的方向前进,不能倒退或者重置。
下面我们通过一个打印一个字符串所有前缀的demo 通过自定义迭代器IteratorProtocol
和自定义集合Sequence
去写一个属于你的集合~
struct PrefixStrIterator:IteratorProtocol {
var string: String
var offset: String.Index
init(string:String) {
self.string = string
offset = string.startIndex
}
///写协议方法
mutating func next() -> String? {
guard offset < string.endIndex else { return nil}
offset = string.index(after: offset)
return String(string[string.startIndex..<offset])
}
}
///step2.创建一个属于你的集合
struct PrefixSequence: Sequence {
var string: String
///协议方法:返回一个迭代器
func makeIterator() -> PrefixStrIterator {
return PrefixStrIterator(string: string)
}
}
///myfirstSquence 我的第一个集合
for prefixStr in PrefixSequence(string: "Hi~LiaoWorking!") {
print(prefixStr)
// H
// Hi
// Hi~
// Hi~L
// Hi~Li
// Hi~Lia
// Hi~Liao
// Hi~LiaoW
// Hi~LiaoWo
// Hi~LiaoWor
// Hi~LiaoWork
// Hi~LiaoWorki
// Hi~LiaoWorkin
// Hi~LiaoWorking
// Hi~LiaoWorking!
}
先说说值语义和引用语义,这两个定义无论在今后的学习还是日常开发细节中会经常遇到~ 敲黑板!
作用对象 | 特性 | |
---|---|---|
值语义 | struct, Int, String, Double等。 | 赋值时不存在引用,复制了一份过去了 |
引用语义 | class | 赋值时存在引用 |
注:但AnyIterator 这个是引用对象。。(协议章中的类型抹消的内容我们再具体说~) |
继续写一个Demo: AnyIterator
还有一个初始化方法就是直接接受next()函数来当做参数。然后通过引用语义的特性,我们可以不创建新的类型就写一个斐波那契迭代器
/// 通过引用语义的特性写斐波那契
func fibsIterator() -> AnyIterator<Any> {
var startNum = (0, 1)
return AnyIterator{
let nextNum = startNum.0
startNum = (startNum.1 , startNum.0 + startNum.1)
return nextNum
}
}
这个是高阶知识点,的确没有第二章的生动。了解一下也挺好啊~~
序列可以是无限
的,而集合是有限
的。
Sequence文档明确指出序列并不保证能被多次遍历。 原因是Sequence协议并不关心里面的序列元素会不会销毁。
迭代器Iterator可以看成即将返回的元素组成的不稳定
序列sequence
Sequence还有一个关联类型 SubSequence
在返回原序列Sequence的切片slice操作
中,SubSequence会被当做返回值的子类。
SubSequence 有一些常用方法
prefix
suffix
dropFirst
dropLast
split
在项目中其实经常会遇到SubSequence,如string的SubSequence等等。。