集合型別協議
3.1序列: sequence
知識點1:滿足sequence協議只需提供一個返回迭代器(iterator)
:的makeIterator方法。 集合<-Sequence<-Iterator
迭代器:Iterator
裡面只有一個方法next( )
public protocol IteratorProtocol {
///關聯型別 Element 指定了迭代器產生的值的型別
///如 subViews的迭代原生型別就是View 可以不用寫,編譯器根據next()的返回值自動判斷。
associatedtype Element
///你只需要在每次呼叫的時候返回下一個值,結束時返回nil
public mutating func next() -> Self.Element?
}
複製程式碼
next( )方法是用 mutating
關鍵字修飾。 幾乎所有的迭代器都要求是可變狀態
,這樣才可以管理在序列中的當前位置—-(這句話的意思到現在還沒太理解。大家可以把自己的理解寫上了,thanks~)
下面我們用迭代器寫一個斐波那契數列(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。
注:迭代器是單向結構
,只能按照增加的方向前進,不能倒退或者重置。
準守序列(sequence)協議
下面我們通過一個列印一個字串所有字首的demo 通過自定義迭代器
和自定義集合
去寫一個屬於你的集合~
第一步: 建立一個迭代器
(Iterator)
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])
}
}
複製程式碼
第二步: 建立一個使用這個迭代器的序列
(sequence)
///step2.建立一個屬於你的集合
struct PrefixSequence: Sequence {
var string: String
///協議方法:返回一個迭代器
func makeIterator() -> PrefixStrIterator {
return PrefixStrIterator(string: string)
}
}
複製程式碼
第三步: run~
///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,應該還有其他型別。待補充。 | 賦值時不存在引用,複製了一份過去了 |
引用語義 | 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協議並不關心裡面的序列元素會不會銷燬。
知識點1:這就是為什麼在集合型別中.first 在序列中並不存在。
序列sequence和迭代器Iterator的關係
迭代器Iterator可以看成即將返回的元素組成的不穩定
序列sequence
子序列
Sequence還有一個關聯型別 SubSequence
在返回原序列Sequence的切片slice操作
中,SubSequence會被當做返回值的子類。
SubSequence 有一些常用方法
prefix
suffix
dropFirst
dropLast
split
複製程式碼
在專案中其實經常會遇到SubSequence,如string的SubSequence等等。。(哈哈才一個,這個不能叫“經常”。其實是會經常遇到SubSequence。不過一時之間想不起來了?)