咱們知道在 Swift 中 Sequence
是 集合類型結構 中的基礎。而在 Sequence
協議的定義當中咱們能夠看到有這麼一句代碼 :bash
associatedtype Iterator : IteratorProtocol複製代碼
咱們看到有兩個關鍵字:associatedtype
與 IteratorProtocol
ide
那麼這個 associatedtype
是什麼意思呢?
看個例子就知道了:函數
咱們定義兩個協議 A
,B
,協議 B 中用到了協議 Aui
protocol A {}
protocol B {
func action(_ pA2: A)
}複製代碼
那麼咱們對協議 A 有兩個實現: A1 與 A2.
咱們對協議 B 有 B1 的實現.代碼以下:this
struct A1: A {}
struct A2: A {}
struct B1: B {
func action(_ pA2: A) {
print("我只認對協議A實現的A2")
}
}複製代碼
這個時候若是咱們要使用 B1 的時候,能夠這樣:spa
let action = B1()
action.action(A2())
action.action(A1())
///我只認對協議A實現的A2
///我只認對協議A實現的A2複製代碼
這個時候咱們在 B1 中對傳入協議 A 的類型想要指定的類型實現而傳入非指定類型的實現編譯器就會報錯怎麼作?
有人講這樣:指針
struct B1: B {
func action(_ pA2: A2) {
print("我只認對協議A實現的A2")
}
}複製代碼
這樣子編譯器就會報錯:Type 'B1' does not conform to protocol 'B'。
這個時候咱們的 associatedtype 就能夠登場了:code
protocol A {}
protocol B {
associatedtype F: A
func action(_ pA2: F)
}
struct A1: A {}
struct A2: A {}
struct B1: B {
func action(_ pA2: A2) {
print("我只認對協議A實現的A2")
}
}
let action = B1()
action.action(A2())
///action.action(A1()) 這個實現就直接報錯了:error: OptimizingCollections.playground:16:15: error: cannot convert value of type 'A1' to expected argument type 'A2' action.action(A1())複製代碼
對 associatedtype 總結就仁者見仁各有各的理解啦!小插曲結束進入正題:↓orm
按住 Command
點進去會發現該協議只有一個函數:cdn
associatedtype Element
public mutating func next() -> Self.Element?複製代碼
如下用 next() 來表示.
可別看它就這麼一句;小,可是 能量 很大!!!
迭代器 是一個知足 IteratorProtocol 協議的類型。
普及一個知識:
具備相同類型的值的一個集合吧。好比簡單的: [Int]
... 都是知足 Sequence
協議
的。
那麼有了序列就會有須要對值遍歷的訪問,那麼就是靠建立一個 迭代器 來進行對元素的訪問。
那麼 next()
的做用就是每次調用的時候返回序列的下一個值,直到最後一個返回 nil
這裏來開始剖析:
它是一個關聯類型用來指定 next() 所產生值的元素類型,好比咱們常常見到的 Iterator.Element
就是 IteratorProtocol 中的定義 Element。那麼迭代器通常會用在那裏呢?
答:自定義序列的擴展類型,好比你想經過字符串 "YinYu"
轉換爲:"["Y", "i", "n", "Y", "u"]"
的擴展類等等等等多的用途!
迭代器在結構上是單向的,顧名思義只能一路 next
對於迭代器相似的操做咱們通常都是用
for <#item#> in <#items#> {
<#code#>
}複製代碼
來完成。 這個通常狀況是不推薦使用的。咱們要玩就要玩高級的。否則怎麼成長呢?是吧!
接下來咱們來完成這樣一個例子的實現,來爲您之後 「拋磚引玉」 一下
首先完成一個 PrefixIterator
實現 IteratorProtocol
協議的 struct
。
public struct PrefixIterator: IteratorProtocol {
let string: String
var offset: String.Index
init(string: String) {
self.string = string
offset = string.startIndex
}
mutating public func next() -> String? {
guard offset < string.endIndex else { return nil }
let previousSet = offset
offset = string.index(after: offset)
return String(string[previousSet..<offset])
}
}複製代碼
咱們分析上面主要有: mutating,字符串切片(String(string[previousSet..<offset]))
那麼有了迭代器,就須要一個裝載迭代器的且知足 Sequence
協議的 struct
.
由於在 Sequence
中咱們發現有這樣的一個函數:
associatedtype Iterator : IteratorProtocol
///Returns an iterator over the elements of this sequence
public func makeIterator() -> Self.Iterator複製代碼
那麼這裏咱們的 PrefixIterator 就至關於 Self.Iterator 類型.
接下來就實現對 Sequence
協議的構造。
public struct PrefixSequence: Sequence {
let string: String
public func makeIterator() -> PrefixIterator {
return PrefixIterator(string: string)
}
}複製代碼
既然實現了 Sequence
協議,那麼咱們就能夠獲得 Map, filter, forEach, dropFirst...
這些集合類型經常使用的函數方法。
利用 Map
依次返回一個字母。從而達到 "YinYu"
到 "Y", "i", "n", "Y", "u"
的轉換
這樣一個 String 擴展方法就出來了:
extension String {
func stringToArr() -> [String] {
return PrefixSequence(string: self).map { $0 }
}
}複製代碼
let strs = "YinYu".stringToArr()
/// ["Y", "i", "n", "Y", "u"]複製代碼
固然若是你想輸出的字面都是大寫很簡單:
$0.uppercased() 這樣就OK啦.
咱們都知道 結構體(Struct)
枚舉(enum)
是 值類型。
當建立一個 class(類)
的時候,class 是 引用類型。
對於引用類型的操做咱們是要萬分當心的,引用類型是具備統一性的通常用 === 判斷兩個變量是否引用了同一個 object。即:指針相等。
那 == 呢? 固然是: 結構相等
通常咱們經過值類型是否執行 深複製來判斷是否具備 值語義.
有深複製就會有 潛複製:
當 Struct 中包含引用類型,這個時候 Struct 進行賦值給其它的變量的時候所發生的複製行爲會存在引用類型的內容是不會複製,其引用自己會被複制。這種行爲就是 淺複製.
能夠對其它的迭代器進行一個包裝,從而迷惑使用者。
這裏要說的就是 AnyIterator
在這樣的狀況下 var 新迭代器 = AnyIterator(舊迭代器)
的時候, 新迭代器是 不具備 值語義的。這種狀況下舊迭代器與新迭代器就不是單獨的了,新迭代器就不是一個結構體。 新迭代器是以一個類實例。
下面代碼見分曉:
var ierator1 = stride(from: 0, to: 10, by: 1).makeIterator()
ierator1.next() /// 0
ierator1.next() /// 1
var ierator2 = ierator1
ierator1.next() /// 2
ierator1.next() /// 3
ierator2.next() /// 2
ierator2.next() /// 3
var ierator3 = AnyIterator(ierator1)
var ierator4 = ierator3
ierator3.next() /// 4
ierator4.next() /// 5
ierator3.next() /// 6
ierator3.next() /// 7複製代碼
彷佛與 Iterator
與 Sequence
同樣,也存在着 AnySequence
.
AnyIterator
也是對 IteratorProtocol
協議的實現.那麼配合 nest() 與對應的 AnySequence
,能夠獲得在不定義任何新類型的狀況下建立迭代器序列。