Swift初見

躍然發表於2014-07-27

更新於2014年7月22日  基於Xcode6-beta 4的系列更新

Swift是蘋果公司今年在WWDC新推出的標牌語言。伴隨著這門語言, 蘋果公司給出了參考文件 Swift reference guide ,我強烈建議大家去學習下。

然而,該參考文件很長!所以,如果你沒有足夠多的時間,或者你想快速的學習Swift,那麼這篇教程很適合你。

這篇Swift教程將歷時15分鐘左右,它將引領你快速瀏覽Swift語言,內容包括變數,控制流,類,最佳實踐,以及更多。

在學習的歷程中,你甚至可以做個方便的小費計時器。

這篇教程,我們需要最新版本的Xcode(寫這篇教程時,最新版本是Xceode 6-Beta版)。你並不需要有Swift或者Objective-C開發經驗,但是如果你有開發經驗會更好些。

:在寫這篇教程時,我們的理解是,因為Xcode 6仍然是beta版,所以我們不能提供截圖。因此直到我們確定可以提供截圖為至在這篇教程中我們將不提供截圖。

Playgrounds介紹

開啟Xcode 6,前往File\New\File.選擇iOS\Source\Playground, 點選下一步。

為檔案命名為 SwiftTutorial.playground, 單擊下一步,儲存檔案至合適的位置。刪除檔案所有內容,以確定我們有一個全新的開始。

:建立playground之後,我們將得到一個錯誤提示,Error running playground: Failed to prepare for communication with playground”。如果這種情況發生,關閉Xcode然後重啟,這個錯誤就會消失了。

playground一個新的檔案型別,它幫我們測試我們的Swift程式碼,並將每行的測試結果在側邊欄顯示出來。例如,新增下面程式碼至playground:

let tutorialTeam = 56
let editorialTeam = 23
let totalTeam = tutorialTeam + editorialTeam

當我們寫下這些程式碼,我們將在側邊欄看到測測試結果。很方便,不是嗎?

Playgrounds是學習Swift(就像你在這篇教程里正在做的一樣),檢驗新的APIs,原型程式碼或演算法,使我們的程式碼視覺化的很好的方法。在接下來的教程中,我們將在playground下工作。

:關於這點,我同樣建議我們把playground檔案(SwiftTutorial.playground) 拖拽到OS X的Dock。然後每當我們想測試我們的Swift程式碼,我們就可以快速使用這個檔案了。

Variables vs. Constants in Swift

新增如下程式碼至playground的底部:

totalTeam += 1

新增這一行後你將發現會報錯誤。這是因為totalTeam是常量,它的值不可修改。我們以關鍵詞let宣告常量。

我們想要把tutorialTeam設定為值可變的變數,所以我們需要用另外一個關鍵字var去宣告它。

用下面程式碼取代totalTeam的初始化:

var totalTeam = tutorialTeam + editorialTeam

現在程式碼無誤了。我們會想,“為什麼不把所有的都設為變數呢,僅僅因為這樣不夠嚴格?”

額,以let宣告常量自有其好處的,它可以是編譯器最優化變現,編譯器不用再格式轉換了。因此,該有let就用let!

Explicit vs. Inferred Typing

目前為止,我們還沒有顯示的為這些常量變數設定型別,因為編譯器擁有足夠的資訊推斷出該怎樣自動處理。

例如,我們設定tutorialTeam為56,編譯器知道56是整型,所以它自動設定tutorialTeam為int型。

然而,如果我們想,我們也可以顯示設定。用下面程式碼取代設定tutorialTeam的那行程式碼。

let tutorialTeam: Int = 56

我們可能想是否需要顯示設定型別,或者讓編譯器為我們推斷型別。我們相信讓編譯器儘可能的為我們自動推斷型別是比較好的,因為這樣我們就可以體驗到Swift的一個主要優勢:程式碼簡潔且宜讀。

因為這些,改變之前的推斷型別:

let tutorialTeam = 56

Basic Types and Control Flow in Swift

現在為止,我們已經看到了Int的一個例子。Int在Swift中用來標識 integer型別,但是Swift中除了Int還有很多型別。

Floats and Doubles

let priceInferred = 19.99
let priceExplicit: Double = 19.99

有兩種型別可以定義帶小數點的十進位制型別:Float 和 Double。Double 有更好的精度,而且是推斷型別的預設選擇。也就意味著priceInferred也是Double型別。

Bools

let onSaleInferred = true
let onSaleExplicit: Bool = false

要注意在Swift中我們使用true/false作為布林值,不像在Objective-C那樣使用YES/NO。

Strings

let nameInferred = "Whoopie Cushion"
let nameExplicit: String = "Whoopie Cushion"

字串,就像你所期望的,不再像在Objective-C那樣使用@標記。這可能會使我們很不習慣,要慢慢適應了。

If statements and string interpolation

if onSaleInferred {
  println("\(nameInferred) on sale for \(priceInferred)!")
} else {
  println("\(nameInferred) at regular price: \(priceInferred)!")
}

這是個像其它語言一樣的if語句例子。條件語句中的大括號是可選的,而即使只有一行程式碼括號也是必須的。

這裡也展示了一個名喚字串插值的新技術的例子。在Swift中,當你想替代字串中某些東西,就用這樣的語法 \(your expression).

這裡,我們也許想知道println程式碼輸出去哪兒了,想看println輸出,開啟助理編輯,像這樣 View\Assistant Editor\Show Assistant Editor.

這是這篇教程目前為止的工程 playground file .


Classes and Methods

在Swift開發中一個很平常的事就是我們要建立類和方法。讓我們現在看看怎麼弄!

首先,刪除playground檔案中所有程式碼,確保我們有一個乾淨的開始。

接下來,我們將建立一個小費計時器類,這個類用來指出在餐廳裡我們該如何付小費。我們將一次只寫一點程式碼,每步輔以解釋。

// 1
class TipCalculator {
}

建立類,鍵入class關鍵字,然後命名我們的類。我們給該類新增了兩個大括號。

如果我們子類化另外一個類,我們需要新增a :然後我們正在子類化的類名。注意我們沒有必要什麼都子類化(不像在Objective-C中我們必須讓類繼承於NSObject或者其子類)。

新增如下程式碼至大括號內:

  // 2
  let total: Double
  let taxPct: Double
  let subtotal: Double

這是建立類的屬性,像建立變數和常量的方式一樣。這裡我們建立了三個常量屬性–一個用作小費的總數(稅後),一個用作標示稅_收所佔小費比例,一個用作小費的小計(稅後)。

注意,我們宣告的屬性在宣告的時候或者例項化的時候必須設定初始值。不然我們必須宣告它們為可選型(之後教程會詳細介紹)。

注:根據 Emily Post Etipedia,小費應當是稅前的。這就是為什麼該類在提交小費之前計算稅前數量。

在前面的塊兒之後新增如下程式碼(在大括號之內):

  // 3
  init(total:Double, taxPct:Double) {
    self.total = total
    self.taxPct = taxPct
    subtotal = total / (taxPct + 1)
  }

這裡為類建立了例項化,類含有兩個引數。在Swift中初始化總是命名為init –如果需要,我們可以不僅僅只有一個初始化,但是每個初始化必須使用不同的引數。

注意,我們給方法的引數類的屬性同樣的名字。因為這兒,我們需要在屬性前新增self關鍵字以此區分方法的引數類的屬性。

因為沒有和subtotal屬性衝突的名字,所以我們不需要在其之前新增self關鍵字,編譯器會自動推斷。相對酷,是不?!

Note: In case you’re wondering, here’s where the subtotal = total / (tipPct + 1) calculation comes from:

(subtotal * taxPct) + subtotal = total
subtotal * (taxPct + 1) = total
subtotal = total / (taxPct + 1)

Thanks to @chewbone for pointing this out!

在上面程式碼之後繼續新增如下程式碼(寫在大括號之內):

  // 4
  func calcTipWithTipPct(tipPct:Double) -> Double {
    return subtotal * tipPct
  }

我們使用func關鍵詞宣告方法。然後我們列出引數(我們必須顯示出型別),新增->符號,最後列出返回型別。

這是決定小費多少的類,subtotal乘以tip percentage,就是如此簡單。

繼續新增如下程式碼(寫在大括號內):

  // 5
  func printPossibleTips() {
    println("15%: \(calcTipWithTipPct(0.15))")
    println("18%: \(calcTipWithTipPct(0.18))")
    println("20%: \(calcTipWithTipPct(0.20))")
  }

這是一個新方法,它列印出三種可能的tips.

注意,當我們在類的例項中呼叫方法的時候,第一個引數不用給出名字(但是其它的需要)。

同樣注意,字串插值不僅限於列印出變數。如果我們樂意,我們可以有各種更加複雜的方法呼叫以及內嵌操作。

在playground最後新增如下程式碼(在大括號之內):

// 6
let tipCalc = TipCalculator(total: 33.25, taxPct: 0.06)
tipCalc.printPossibleTips()

最後,我們建立一個小費計算器的例項,該例項呼叫方法列印可能的小費。

現在playground應該看起來像現在這樣:

// 1
class TipCalculator {
 
  // 2
  let total: Double
  let taxPct: Double
  let subtotal: Double
 
  // 3
  init(total:Double, taxPct:Double) {
    self.total = total
    self.taxPct = taxPct
    subtotal = total / (taxPct + 1)
  }
 
  // 4
  func calcTipWithTipPct(tipPct:Double) -> Double {
    return subtotal * tipPct
  }
 
  // 5
  func printPossibleTips() {
    println("15%: \(calcTipWithTipPct(0.15))")
    println("18%: \(calcTipWithTipPct(0.18))")
    println("20%: \(calcTipWithTipPct(0.20))")
  }
 
}
 
// 6
let tipCalc = TipCalculator(total: 33.25, taxPct: 0.06)
tipCalc.printPossibleTips()

檢查助理編輯器結果。

Arrays and For Loops

到目前為止,上面的程式碼有一些重複,我們以不同小費比率呼叫了calcTipWithTotal方法幾次。我們可以使用array減少重複。

使用以下程式碼取代printPossibleTips的內容:

let possibleTipsInferred = [0.15, 0.18, 0.20]
let possibleTipsExplicit:[Double] = [0.15, 0.18, 0.20]

這裡展示了一個建立推斷型和顯式型doubles型陣列的例子。 [Double]Array<Double>的縮寫。

然後在下面繼續新增如下程式碼:

for possibleTip in possibleTipsInferred {
  println("\(possibleTip*100)%: \(calcTipWithTipPct(possibleTip))")
}

在陣列中列舉內容就像在Objective-C中快速列舉,只是這裡不需要分號。

我們也可以像這樣寫迴圈:

for i in 0..<possibleTipsInferred.count {
  let possibleTip = possibleTipsInferred[i]
  println("\(possibleTip*100)%: \(calcTipWithTipPct(possibleTip))")
}

<運算子是一種非包容性的範圍操作符,不包括上界值。還有一個...運算子是包容性的。

陣列有一個數量屬性,該屬性標誌陣列中內容個數。我們也可以在陣列中定位某個特定的元素,像這樣arrayName[index] 。

Dictionaries

讓我們為我們的小費計算器做最後的修改。取代僅僅列印小費,我們返回一個包含結果的字典。這使得在某些使用者介面的應用程式中更容易將結果顯示出來。

刪除printPossibleTips方法,以如下方法更新:

// 1
func returnPossibleTips() -> [Int: Double] {
 
  let possibleTipsInferred = [0.15, 0.18, 0.20]
  let possibleTipsExplicit:[Double] = [0.15, 0.18, 0.20]
 
  // 2
  var retval = Dictionary<Int, Double>()
  for possibleTip in possibleTipsInferred {
    let intPct = Int(possibleTip*100)
    // 3
    retval[intPct] = calcTipWithTipPct(possibleTip)
  }
  return retval
 
}

讓我們一點點來分析:

  1. 我們標記方法返回型別為字典,key型別為Int(小費比率是整型,如15或20),value型別為Double(計算小費)。 [Int: Double]Dictionary<Int, Double>的縮寫。
  2. 建立一個空字典。因為要修改字典值,我們應該設定字典型別為可變字典(使用var)而不是常量(像let)。不然我們將得到編譯錯誤。
  3. 給字典新增項,很像Objective-C語法。

最後,修改playground最後一行,呼叫該方法:

tipCalc.returnPossibleTips()

Once the playground evaluates, you should see the results as a dictionary in the inspector (click the eyeball for an expanded view).

一旦playground評估,我們在檢查器應該看到返回值為字典的結果(點選eyeball看擴充套件檢視)。

O(∩_∩)O哈哈~,就是這了–恭喜!使用Swift我們已經有了一個完全的高效的小費計算器。

Where To Go From Here?

這是最終這篇教程的最終demo final playground file.

想要學更多?那麼接著讀下篇( next part of this series)吧!下篇我們將學習如何為該應用建立使用者介面。或者點選我的新書new Swift books!

希望這篇教程讓您享用了。歡迎來到Swift世界!:]


再次做翻譯,感覺翻譯真不易哦!翻譯出來容易,翻譯成經典就太難了!鑑於目前個人能力所限,不免有誤。望讀到的朋友指點扶正!

相關文章