卷卷的知識- Swift 高階題解答區

語言: CN / TW / HK

3.1 一個 Sequence 的索引是不是一定從 0 開始?

不一定, 兩個 for in 並不能保證都是從 0 開始, 且輸出結果一致, 官方文件如下:

Repeated Access  \ The Sequence protocol makes no requirement on conforming types regarding whether they will be destructively consumed by iteration. As a consequence, don’t assume that multiple for-in loops on a sequence will either resume iteration or restart from the beginning:

``` for element in sequence { if ... some condition { break } }

for element in sequence { // No defined behavior } ```

有些同學還是不太理解, 我寫了一個demo 當作參考

``` class Countdown: Sequence, IteratorProtocol { var count: Int init(count: Int) { self.count = count } func next() -> Int? { if count == 0 { return nil } else { defer { count -= 1 } return count } } }

var countDown = Countdown(count: 5) print("begin for in 1") for c in countDown { print(c) } print("end for in 1") print("begin for in 2") for c in countDown { print(c) } print("end for in 2")

最後輸出的結果是: begin for in 1 5 4 3 2 1 end for in 1 begin for in 2 end for in 2 `` 很明顯, 第二次沒有輸出任何結果, 原因就是在第二次for in 的時候, 並沒有將count` 重置。

//

``` //系統方法呼叫 print("start----") let numbers = [2, 3, 5, 7] var numbersIterator = numbers.makeIterator() while let num = numbersIterator.next() { print(num) } print("midle----") while let num = numbersIterator.next() { print(num) } print("end----")

輸出: start---- 2 3 5 7 midle---- end---- ```

3.2 陣列都實現了哪些協議

  • MutableCollection, 實現了可修改的陣列, 如 a[1] = 2\ var streets = ["Adams", "Bryant", "Channing", "Douglas", "Evarts"] streets[1] = "Butler" print(streets[1])         // Prints "Butler"

  • ExpressibleByArrayLiteral, 實現了陣列可以從[1, 2, 3] 這種字面值初始化的能力

``` let countryCodes = ["BR": "Brazil", "GH": "Ghana","JP": "Japan", "US": "United States"] // 'countryCodes' has type [String: String]

print(countryCodes["BR"]!) // Prints "Brazil" ```

3.3 如何自定義模式匹配

\ \

3.4 autoclosure 的作用

自動閉包, 會自動將某一個表示式封裝為閉包. 如 func autoClosureFunction(_ closure: @autoclosure () -> Int) { closure() } autoClosureFunction(1)

3.5 編譯選項 whole module optmization 優化了什麼

編譯器可以跨檔案優化編譯程式碼, 不侷限於一個檔案

3.6 下面程式碼中 mutating 的作用是什麼

struct Person { var name: String { mutating get { return store } } } 讓不可變物件無法訪問 name 屬性

3.7 如何讓自定義物件支援字面量初始化

有幾個協議, 分別是\ ExpressibleByArrayLiteral 可以由陣列形式初始化\ ExpressibleByDictionaryLiteral 可以由字典形式初始化\ ExpressibleByNilLiteral 可以由nil 值初始化\ ExpressibleByIntegerLiteral 可以由整數值初始化\ ExpressibleByFloatLiteral 可以由浮點數初始化\ ExpressibleByBooleanLiteral 可以由布林值初始化\ 1 ExpressibleByUnicodeScalarLiteral\ 2 ExpressibleByExtendedGraphemeClusterLiteral\ 3 ExpressibleByStringLiteral\ 這三種都是由字串初始化, 上面兩種(1,2)包含有 Unicode 字元和特殊字元\

3.8 dynamic framework 和 static framework 的區別是什麼

靜態庫和動態庫, 靜態庫是每一個程式單獨打包一份, 而動態庫則是多個程式之間共享\

3.9 為什麼陣列索引越界會崩潰,而字典用下標取值時 key 沒有對應值的話返回的是 nil 不會崩潰

陣列的物件的儲蓄地址是連續的,如果越界了,那取到的地址不一定可用,所以報錯。畢竟還是需要有可以信任的部分的 ``` struct Array { subscript(index: Int) -> Element }

struct Dictionary { subscript(key: Key) -> Value? } ``` 1 陣列索引訪問的是一段連續地址,越界訪問也能訪問到記憶體,但這段記憶體不一定可用,所以會引起Crash.\ 2 字典的key並沒有對應確定的記憶體地址,所以是安全的.

3. 10 一個函式的引數型別只要是數字(Int、Float)都可以,要怎麼表示

讓引數都遵循 Numeric 協議 func myMethod<T>(_ value: T) where T: Numeric { print(value + 1) } myMethod(1.11) myMethod(2)  輸出: 2.1100000000000003 3

3. 11 lazy 懶載入的實現

lazy懶載入,oc中實利用get方法實現, swift利用閉包實現.比如

private lazy var navLeftButton = { () -> UIButton in let btn = UIButton(type: .custom) btn.frame = CGRect(x: 0, y: 0, width: 50, height: 30) btn.setImage(UIImage(named:"back"), for: .normal) btn.addTarget(self, action: #selector(self.back), for: .touchUpInside) return btn }()