Swift學習筆記(一)--基礎與操作符

前言

已經很久沒有在簡書上更新了, 最近一直在忙于開發業務, 實在沒有太多時間來沉淀, 再機上比較懶, 所以就一直沒有更新了. 好不容易看了一些和繪圖性能相關的東西, 但是因為有的大牛已經講的比較清楚了, 所以也不多贅述什么了, 有興趣的可以去看YYKit作者寫的iOS 保持界面流暢的技巧, 任何關注繪圖性能的同學都應該仔細讀讀這一篇博客

原因

Swift目前已經到了2.1版, 總算是相對穩定了, 之前有關注, 但是并不打算快速切入, 畢竟只是初版, 之后改動的可能性也是很大的, 加之那個時候切入, 其他的小伙伴也不一定愿意接受, 到時候只能自己維護自己的代碼, 還要去改別人的代碼, 要切換思維, 還是很浪費時間且沒有效率的事情.

稍微談一下我被Swift吸引的地方吧, 一個是optional value, 一個是面向協議編程, 還有就是extension

我目前也在學習中, 資料是蘋果自己出的資料包括iBooks里面的和WWDC的視頻, 我也會跟著資料一篇篇講下去, 講一些我覺得比較關鍵的點或者是需要注意的地方. 到時候會持續更新, 歡迎大家一起探討, 有誤之處還請大家指正.

基本變化

  1. 語法風格完全脫離了ObjC, 與Java類似了
  2. 每一條語句不需要;結尾了, 但是結尾也不會報錯, 大多數情況下;都沒有什么用了, 還有就是對空格要求嚴格一些了, 有些地方必須要空格,不然會報錯的
  3. 沒有宏定義了
  4. 條件判斷不需要括號包圍了
  5. 增加了大量的關鍵字, 不用也可以, 但是用了會使得代碼很簡潔易懂
  6. 去掉了block, 引入了closure(閉包), 其實差不多的作用, 就是寫法不同
  7. 沒有了id類型, 換成了AnyObject
  8. switch的匹配更加靈活強大, 而不僅限于ObjC里面的整數, 而且對每個case都是自動添加break
    ...
    還是不一一列舉了, 畢竟是一門全新的語言, 一直舉下去也沒什么意義, 還是直接切入正題吧. PS: 大家多用playground來測試代碼吧 還是很方便的, 就是代碼多了會慢一點

基礎篇(The Basics)

  1. Swift中用var來聲明變量, let來聲明常量. 導致了Swift里面只有Array類型, 沒有MutableArray類型(其它的集合類型也是一樣), 因為var則代表可變, let則代表不可變. 例如:
var varArray: Array = [AnyObject]()  // 初始化一個空數組, 可以看到, AnyObject就代表著id
varArray.append(1)  // 插入一個整數, 注意, 這里不需要@1, 在Swift Int也是一個對象(不是int)
varArray.append("2") // 字符串也不需要@了
let constArray: Array = [1,2,3] // 不可變數組
constArray.append(3) // error: 不可以向不可變的數組插入元素
  1. 類型推導: 聲明變量如果賦了初值, 那么就可以省略掉后面的類型, 例如:
    var number = 1 // 編譯器通過 = 1來推導出number類型為Int

  2. 變量名支持Unicode編碼字符, 這個我覺得沒什么用, 應該沒有人會真的用吧?

  3. 打印函數: print, 與C++類似, 支持重名函數, 所以print有多種用法, 但是都比較容易懂, playground實驗一下就好, 個人感覺還是很方便的, 例如:

let name = "Ryan"
print("My name is \(name)") // 直接用\(variable)的方式直接代入變量
  1. 之前說了分號(;)很少用了, 代表還是有用的地方的, 比如你要在一行里面執行多條語句,就用分號(;)分割

  2. Bool值由YES,NO改為了更加常見的true和false, 同時整數0與非0不能再代表false和true了, 因為Int沒有實現BooleanType協議, 這是蘋果故意的, 因為你自己extension Int: BooleanType的話, 編譯器會明確告訴你, 不允許這么干, 應該是蘋果想開發者更顯式的寫明條件, 避免出現意外的錯誤

  3. 元組(Tuples)
    元組是一個很棒的東西, 以前在寫C語言的時候, 因為返回值只能返回一個東西, 所以還要特意傳入一個變量的地址來寫入額外的信息, 或者返回一個結構體, OC里面也差不多是這樣的, Swift引入了元組就更加強大了, 可以返回多個值, 用()包起來就可以了, 我估計其實是編譯器幫我們實現了一個結構體, 例子:

let http404Error = (404, "Not Found") // 默認用http404Error.0/.1來訪問404和"Not Found", 如果要指定, 則let http404Error = (code:404, reason:"Not Found"), 當然.0和.1還是可用的.
// 通過數據的訪問形式, 我們的確是可以猜測其實就是編譯器自己實現了一個結構體

Tip:元組在用法可不止這些, 還可以寫出最簡單的交換2個變量的值的代碼. 以前我們都是, t = a, a = b, b = t 這種類型的寫法, 整型還有更簡單的寫法, 但是用元素就是一行代碼:
(a,b) = (b,a)

  1. Optionals: (我還是保持原文吧, 翻譯為可選類型總是感覺很奇怪).
    這個東西其實和ObjC新引入nullable差不多, 就是告訴開發者這個東西可能是為nil, 你要好好判斷一下, 如果不判斷就用, 首先會有編譯報錯, 告訴你要用感嘆號(!)來獲得這個值(數據叫做Unwrapping), 然后你解決了這個問題, 但是它其實可能是為空的, 到時候就會導致runtime error, 直接給掛了. 所以, 蘋果說Swift的安全, 這是其一, 例子:
var serverResponseCode: Int?
serverResponseCode = 1
//var code: Int = serverResponseCode // error: 要用!來取值

  if convertedNumber != nil {  // 先判斷, 后使用
    print("convertedNumber has an integer value of \(convertedNumber!).")
}

至于optional binding, 其實就是賦值一次, 省略了感嘆號(!)但是加了一個if let(if let得到的是常量, 所以也會有if var的), 如: // 1.30更新, 增加if var

var possibleNumber = "a12"
if let actualNumber = Int(possibleNumber) {
    print("\'\(possibleNumber)\' has an integer value of \(actualNumber)")
} else {
    print("\'\(possibleNumber)\' could not be converted to an integer")
}

正如官方而言, Optional value是一個黑盒子, 在使用之前不之前里面是有東西還是空的, 這也就是是為什么你要用!來取值, 不然你取的就是這個盒子.
// 1.25日添加:
Optional還有一種加感嘆號(!)的用法, 這種用法讓你直接回到了ObjC的寫法上了, 不需要額外去拆包, 但是很可惜, Swift對nil發送消息是會crash的, 所以要謹慎, 畢竟這種寫法是不安全的. 例如:

var aStr: String!
//aStr.characters.count //runtime error
aStr = "123"
aStr.characters.count // print 3
  1. 錯誤處理:
    錯誤處理是一大塊內容, 這里先點一下, 按照Swift的設計, 拋出異常在Swift里面應該會用的比ObjC更多, 一個函數通過throws來拋出異常, 調用函數的地方用do, try, catch來捕獲, 如:
func makeASandwich() throws {
    // ...
}
 
  do {
    try makeASandwich()
    eatASandwich()
} catch Error.OutOfCleanDishes {
    washDishes()
} catch Error.MissingIngredients(let ingredients) {
    buyGroceries(ingredients)
}

至于為什么要加個do, 而不是Java里面的直接try+catch, 我覺得應該是異常處理其實是比較影響性能的, 所以ObjC是不推薦用異常來處理錯誤的, 因為能少try的語句盡量少try, 所以上面的例子中, 實際上只對makeASandwich()進行了try, 而eatASandwich()則沒有, 這樣可以讓盡量少的代碼在try里面, 提高性能. 哈, 個人猜測...

  1. 斷言:
    沒什么特別的, 和之前的差不多, 例如:
let age = -3
assert(age >= 0, "A person's age cannot be less than zero")

值得關注的是, 到底什么時候該用斷言, 什么時候不該用? 蘋果的說法是:
a.下標越界的時候用
b. 如果傳入了一個無效的參數, 不滿足函數的需求
c. 傳入了nil, 但是函數本身需要一個非nil的參數

assertion可以在開發階段就把問題通過crash的方式暴露出來, 而不是出現奇奇怪怪的結果, 然后一步步斷點去查. 當然, 記得在Xcode中設置, release打包中去掉斷言crash的選項...

這一部分值得說道的差不多就這么多了, 具體可以參考蘋果的文檔
里面對數值類型做了很多有意思的介紹, 比如老外喜歡千分位, 1000000要寫成1,000,000, 在代碼里面1000000不能一眼就看出來是多少, 所以有這樣的寫法:
var oneMillion = 1_000_000, 估計是編譯器看到數值類型有_就直接刪掉了.
還有很多有意思的tip, 但是用的地方可能不多就不多說了, 大家自己去探索吧.

基本運算符(Basic Operators)

其實這一章更加簡單, 基本上沒有差別, 只是Swift和C++一樣, 也有也運算符重載, 可以豐富很多寫法.
這里只記錄一些區別的地方:

  1. 賦值語句不再有返回值, 所以以前在ObjC里面寫的
if (self = [super init]) 
{
// ...
}

在Swift里面還這么玩就報錯了, 其實這是對原本要寫==寫成=的一種保護吧

  1. 三目運算符:
    三目運算符不知道各位用的多不多, 我個人用的比較多, 比如我的block執行宏就是
#define RUN_BLOCK_IF_NONNIL(block,...) !(block)?:(block)(__VA_ARGS__);

這里對block進行為空判斷, 為空則返回自身, 也就是nil, 否則傳入參數執行之.
但是對于第一個參數返回自身省略的寫法, Swift是這樣的:

let defaultColorName = "red"
var userDefinedColorName: String?  // defaults to nil
var colorNameToUse = userDefinedColorName ?? defaultColorName

用??替換掉了?:
但是, 普通的用法, 也就是:前后都寫的, 還是一樣的

  1. 求余數(%):
    在C和ObjC里面, %都只能對整數使用, 但是Swift進行了拓展, 可以對浮點數使用了:
8 % 2.5   // 結果為 0.5
  1. 范圍操作符:
    也就是表示范圍的, 有兩種寫法: 1...3 代表1, 2, 3, 如果不想包含后面的數字, 就要寫成1..<3. (話說之前的版本是用..來代表..<的, 在新版進行了修改)
    除此之外, Swift專門有個Range類型來表示之:
var range: Range = 1...3 // 會被編譯器描述成1..<4

其它的操作符基本上的一直的, 想要查看細節可以看[蘋果文檔](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html#//apple_ref/doc/uid/TP40014097-CH6-ID60)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 1、隨機數 不需要隨機數種子 arc4random()%N + begin:產生begin~begin+N的隨機數...
    我是小胡胡123閱讀 4,223評論 0 2
  • Swift 介紹 簡介 Swift 語言由蘋果公司在 2014 年推出,用來撰寫 OS X 和 iOS 應用程序 ...
    大L君閱讀 3,301評論 3 25
  • 1、范型范型所解決的問題 函數、方法、類型:類,結構體,枚舉,元組類型,協議參數,返回值,成員函數參數,成員屬性類...
    我是小胡胡123閱讀 858評論 0 1
  • 關于 Swift 重要這個文檔所包含的準備信息, 是關于開發的 API 和技術的。這個信息可能會改變, 根據這個文...
    無灃閱讀 4,372評論 1 27
  • 忙碌的周末不能換來一夜的安睡,幸好,小羊為我借了一本木心的書。早餐時間,我們討論了一會兒木心,我希望他先了解,有興...
    夏洛的后花園閱讀 210評論 0 1