Swift進階 - 12個技巧

據說你已經學習Swift幾個月了,有沒有想更進一步成爲Swift高手的想法?我這裏有11招祕技,各位施主且聽我慢慢道來,結個善緣。javascript

1. 擴展(Extension)

任務: 求數字的平方。php

// 菜鳥版 func square(x: Int) -> Int { return x * x } var squaredOfFive = square(x: 5) square(x: squaredOfFive) // 625 

爲了求5的四次方咱們被迫建立變量 squaredOfFive — 高手可不喜歡被迫定義一個無用的變量。java

// 高手版 extension Int { var squared: Int { return self * self } } 5.squared // 25 5.squared.squared // 625 

2. 泛型(Generics)

任務:打印輸出數組內全部的元素。編程

// 菜鳥版 var stringArray = ["金庸", "古龍", "梁羽生"] var intArray = [1, 3, 4, 5, 6] var doubleArray = [1.0, 2.0, 3.0] func printStringArray(a: [String]) { for s in a { print(s) } } func printIntArray(a: [Int]) { for i in a { print(i) } } func printDoubleArray(a: [Double]) {for d in a { print(d) } } 

竟然要定義這麼多函數? 菜鳥能忍高手不能忍!!!數組

// 高手版
func printElementFromArray<T>(a: [T]) {
        for element in a { print(element) } } 

3. For 遍歷 vs While 遍歷

任務:打印 5 次 陸家嘴安全

// 菜鳥版 var i = 0 while 5 > i { print("陸家嘴") i += 1 } 

被迫定義了變量 i 來確保打印 陸家嘴 5 次。
注意定義越多的變量,越多的潛在風險,越多的生活問題。這就是蝴蝶效應,你難道想X生活不和諧?bash

// 高手版
for _ in 1...5 { print("陸家嘴") } 

上面的代碼實在是簡潔,美妙。閉包

4. Gaurd let vs if let

任務 : 讓咱們寫個歡迎新用戶的程序。app

var myUsername: Double? var myPassword: Double? // 菜鳥版 func userLogIn() { if let username = myUsername { if let password = myPassword { print("華山派歡迎, \(username)"!) } } } 

這些使人討厭的嵌套代碼,咱們要消滅它函數式編程

// 高手版
func userLogIn() { guard let username = myUsername, let password = myPassword else { return } print("華山派歡迎, \(username)!") } 

注意這裏若是myUsername 或 myPassword nil,都會提早結束,不然就會打印 「優衣庫歡迎, XXX」

5. 計算屬性 vs 函數

任務:計算圓的直徑

// 菜鳥版 func getDiameter(radius: Double) -> Double { return radius * 2} func getRadius(diameter: Double) -> Double { return diameter / 2} getDiameter(radius: 10) // return 20 getRadius(diameter: 200) // return 100 getRadius(diameter: 600) // return 300 

上面咱們建立了2個毫無關係的函數,但是直徑和周長二者真的沒有關係嗎?

// 高手版 var radius: Double = 10 var diameter: Double { get { return radius * 2} set { radius = newValue / 2} } radius // 10 diameter // 20 diameter = 1000 radius // 500 

如今半徑和直徑相互依賴,真實地反應了二者的關係。
記得上面說的蝴蝶效應嗎? 越少的依賴,代碼越簡潔,問題越少,生活越美好!

6. 枚舉 - 類型安全

任務:賣門票

// 菜鳥版 switch "Adult" { case "Adult": print("請付 50 元") case "Child": print("請付 25 元") case "Senior": print("請付 30 元") default: print("你確認不是殭屍嗎,哥們?") } 

「Adult」, 「Child」, 「Senior」 這裏都是硬編碼,你每次須要輸入手動輸入這些字符,記得咱們上面講到的嗎? 手動鍵入越少,錯誤越少,生活越美好。

// 高手版 enum People { case adult, child, senior } switch People.adult { case .adult: print("請付 50 元") case .child: print("請付 25 元") case .senior: print("請付 30 元") default: print("你確認不是殭屍嗎,哥們?") } 

這樣你就避免了不當心輸入錯誤的問題,由於 「.adult」, 「.child」, 「.senior」 被定義成了enum', 任何不在預約義範圍內的實例都會被Xcode絕不留情的指出來,合理利用集成開發環境是高手必備的。

7. 空合運算符

任務: 用戶選擇微博主體顏色。

// 菜鳥版 var userChosenColor: String? var defaultColor = "Red" var colorToUse = "" if let Color = userChosenColor { colorToUse = Color } else { colorToUse = defaultColor } 

這也太臃腫了吧,讓咱們來減減肥。

// 高手版 var colorToUse = userChosenColor ?? defaultColor 

稍微解釋一下, 如 userChosenColor 爲 nil, 則選擇 defaultColor, 不然則userChosenColor.
其實空合運算符是對如下代碼的簡短表達方法。

a != nil ? a! : b 

8. 函數式編程

任務: 獲取偶數。

// 菜鳥版 var newEvens = [Int]() for i in 1...10 { if i % 2 == 0 { newEvens.append(i) } } print(newEvens) // [2, 4, 6, 8, 10] 

這種for循環真是冗長,讓人看的昏昏欲睡。

// 高手版 var evens = (1...10).filter { $0 % 2 == 0 } print(evens) // [2, 4, 6, 8, 10] 

有沒有感受函數式編程讓你看起來聰明多了。

9. 閉包 vs 函數

任務: 求兩個數字的和。

// 菜鳥版 func sum(x: Int, y: Int) -> Int { return x + y } var result = sum(x: 5, y: 6) // 11 

爲了這個功能我還須要記住函數名 和 變量名? 能不能少一個呢?

// 高手版 var sumUsingClosure: (Int, Int) -> (Int) = { $0 + $1 } sumUsingClosure(5, 6) // 11 

10. 屬性觀測器

任務:計算圓的直徑

// 菜鳥版 var radius = 10.0 func getDiameter(radius: Double) -> Double { return radius * 2 } getDiameter(radius: radius) // return 20 

這裏是不須要專門定義函數的。

// 高手版 var diameter = 0 var radius: Double = 10 { willSet { print("準備賦值中") } didSet { diameter =radius * 2} } } radius = 10 // 準備賦值中 diameter // 20.0 

willSet 會在給變量radius賦值前調用,而 didSet 會在給變量radius賦值後調用。

11.便利初始化

任務: 一我的有多少根手指和腳趾

// 菜鳥版 class Human { var finger: Int var toe: Int init(finger: Int, toe: Int) { self.finger = finger self.toe = toe } } var daDi = Human(finger: 10, toe: 10) daDi.finger // 10 daDi.toe // 10 

由於絕大部分人都有十根手指和腳趾,能夠初始化時預先賦值。

// 高手版 class Human { var finger: Int var toe: Int init(finger: Int, toe: Int) { self.finger = finger self.toe = toe } convenience init() { self.init(finger: 10, toe: 10) // 調用主初始化方法 } } var daDi = Human() daDi.finger // 10 daDi.toe // 10 

Swift中能夠在init初始化方法前加上convenience關鍵字,這類方法主要提供使用上的方便。

全部的convenience初始化方法都必須調用同一個類中的頂級初始化方法完成初始化。另外convenience的初始化方法是不能被子類重寫或從子類中以super的方式被調用的。

12. 延遲初始化

任務: 定義一個包含pi常量做爲屬性的類。

// 菜鳥版 class MathHelper { var pi: Double = { // 計算pi return resultOfCalculation }() } 

計算pi的工做量是繁重的,且對於調用者不是必須的,能夠假想下MathHelper內包含數十個類pi常量的場景,若是不在使用的時候再初始化常量會浪費多少寶貴的計算資源。

// 高手版 class MathHelper { lazy var pi: Double = { // 計算pi return resultOfCalculation }() } 

lazy 一方面可讓初始化成本較高的變量延遲初始化,提升資源利用效率。另外一方面能夠延遲初始化具備外部依賴的屬性變量。

class Person { var name: String lazy var personalizedGreeting: String = { [unowned self] in return "Hello, \(self.name)!" }() init(name: String) { self.name = name } } 

上面的例子中,屬性personalizedGreeting依賴於變量name。

十二條技巧講述完畢,打完收工。

做者:豆志昂揚 連接:https://www.jianshu.com/p/eabaaae88533 來源:簡書 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。
相關文章
相關標籤/搜索