簡介
這是一個Swift語言教程,基于最新的iOS 9,Xcode 7.3和Swift 2.2,會為你介紹Swift編程非?;A(chǔ)的內(nèi)容。從電腦如何工作的全程基本原理到語言結(jié)構(gòu),你會足夠了解這門語言,來處理數(shù)據(jù)和管理代碼的行為。
快速鏈接
一個下午讓你掌握Swift基礎(chǔ) ( 1/9 ) 編程本質(zhì) & Playground基礎(chǔ)
一個下午讓你掌握Swift基礎(chǔ) ( 2/9 ) 變量 & 常量
一個下午讓你掌握Swift基礎(chǔ) ( 3/9 ) 數(shù)字類型 & 操作
一個下午讓你掌握Swift基礎(chǔ) ( 4/9 ) 字符串
一個下午讓你掌握Swift基礎(chǔ) ( 5/9 ) 做判斷
一個下午讓你掌握Swift基礎(chǔ) ( 6/9 ) 重復(fù)步驟
一個下午讓你掌握Swift基礎(chǔ) ( 7/9 ) 函數(shù)
一個下午讓你掌握Swift基礎(chǔ) ( 8/9 ) 閉包
一個下午讓你掌握Swift基礎(chǔ) ( 9/9 ) 可選值
可選值
你目前遇到的所有變量和常量都有實際的值。當你有一個字符串變量的時候,比如 var name,它有一個相關(guān)的字符串值,例如“張嘉夫”。它可能是一個空字符串,像 “”,但盡管如此,還是有一個可以訪問到的值。
那是 Swift 自帶的安全特色之一:如果說類型是 Int 或 String 那么就有一個實際的整數(shù)或字符串在那里,有保證的。
這篇文章會為你介紹可選值(optionals)的概念,一個特殊的 Swift 類型,不只可以表示一個值,也可以沒有值。在這篇文章的最后,你會知道為什么需要可選值,以及如何安全的使用它們。
介紹 nil
有時候,有一個沒有值的值是很有用的。想象一個場景,你需要訪問一個人的認證信息。你想要存儲這個人的名字、年齡和職業(yè)。名字和年齡都是必須有值的東西—每個人都有。但不是每個人都有工作,所以職業(yè)這個值的缺失就是你需要處理的事情。
讓我們實際看看這個情況。
在不知道可選值的情況下,這是你可能去表示一個人的名字、年齡和職業(yè)的方式:
varname:String="張嘉夫"varage: Int =23varoccupation:String="軟件開發(fā)者 & 作家"
但如果我被解雇了呢?也許我中了彩票然后再也不想工作了(我真的想!)。這時候能夠訪問一個不存在的值就會很有用了。
為什么你不能就用一個空的字符串呢?好吧,你可以!讓我們討論一下那樣會怎么做,以及為什么可選值是一個更好的選項。
標記值
一個有效值,用來表示不存在的,叫做標記值(sentinel value)。這是前一個例子里你的空字符串就會是這樣。
讓我們看一下另一個例子。假設(shè)你寫了一些代碼,從服務(wù)器上請求什么東西,那么你可以用一個變量來存儲服務(wù)器返回的任意錯誤代碼:
varerrorCode:Int=0
在成功的時候,你可以用零來表示沒有錯誤。意味著 0 是標記值。
就像職業(yè)的空字符串,這可以奏效,但對于程序員有潛在的混淆的風險。0 實際上可能是一個有效的錯誤代碼—也或許在未來會是。無論怎么樣,你不能完全確定這是沒有錯誤的。
這兩種情況下,如果有一個特殊類型可以表示值的缺失就會更好。這樣什么時候有值什么時候沒有就很明確了。
Nil表示值的缺失,你會看到 Swift 如何用相當優(yōu)雅的方式來直接把這個概念并入語言中。
其他有一些編程語言只用標記值。有一些,比如 Objective-C,有 ni 的概念,但僅僅是零的同義詞。只是另一個標記值罷了。
Swift 介紹了一個全新的類型,叫做可選值來處理一個值可能是或不是 nil。這意味著如果你在處理一個非可選值類型,那么它就被保證了一定有值,不需要去擔心有沒有值??偸怯械?。相似的,如果你在用一個可選值類型,那你就必須要考慮 nil 情況了。它移除了使用標記值帶來的歧義。
介紹可選值
可選值是 Swift 對于同時表示值和值的缺失問題的解決方案。一個可選值類型可以引用一個值或是 nil。
把可選值想象為一個盒子:它要么包含一個值,要么沒有。當它沒有包含值的時候,它被認為包含了 nil。盒子本身總是存在;它一直在這里,你可以打開然后看看里面。
另一方面,字符串或整數(shù),周圍并沒有這個盒子。相關(guān)那里總有一個值,比如 “hello” 或 42。記住,非可選值類型確保有一個實際值。
**注意:**學過物理的這時候可能會想起薛定諤的貓。可選值和它有一點像,除了這不是一個生死攸關(guān)的問題!
用下面的語法聲明可選值類型:
varerrorCode:Int?
它和標準聲明之間的唯一區(qū)別就是類型末尾的問號。這個例子里,errorCode 是“ Int 可選值”。這意味著變量本身就像一個盒子,包含一個 Int 或 nil。
設(shè)置值很簡單。你可以設(shè)置它為一個 Int,像這樣:
errorCode =100
或者你可以設(shè)置它為 ni,像這樣:
errorCode =nil
圖表可以幫助你形象化理解正在發(fā)生什么:
可選值盒子永遠存在。當你給變量賦值 100 的時候,你在用值來填滿盒子。當你給變量賦值 nil 的時候,你在清空盒子。
花幾分鐘想一下這個概念。用盒子的類比會是一個巨大的幫助,在你讀完這篇文章剩下的部分的時候,然后開始使用可選值。
迷你練習
創(chuàng)建一個叫做 myFavoriteSong 的 String 可選值。如果你有一首最愛的歌,就把它設(shè)置為表示那首歌。如果你有不止一首或者沒有最愛的,就設(shè)置可選值為 nil。
拆包可選值
有可選值一切都很好,但你應(yīng)該會好奇怎么看到盒子里面,操作它所包含的值。
讓我們看看打印可選值的值得時候會發(fā)生什么:
letageInteger: Int? =23print(ageInteger)
如下輸出:
Optional(30)
那不是你真正想要的—盡管如果仔細想一想,它還是有意義的。你的代碼輸出了盒子。結(jié)果說:“ ageInteger 是一個可選值,包含值 30”。
要看這個值類型如何區(qū)別于非可選值類型,那就讓我們看看如果嘗試把 ageInteger 當一個正常整數(shù)來使用會怎么樣:
print(ageInteger+1)
代碼觸發(fā)了一個錯誤:
error: value of optional type'Int?'notunwrapped; did you mean touse'!'or'?'?(錯誤:可選值類型'Int?'的值沒有被拆包;你是不是想使用'!'或'?'?)
不正確是因為你嘗試把一個整數(shù)加到一個盒子上—不是盒子里面的值,而是盒子本身。這是沒有意義的!
強制拆包
錯誤信息給了解決方案的指示:它告訴你可選值“沒有被拆包”。你需要從盒子里把值拆出來。就像過圣誕節(jié)!
來看看怎么做。考慮如下聲明:
varauthorName:String? ="張嘉夫"
你可以用兩種不同的方法來拆包可選值。第一種叫做強制拆包(force unwrapping),像這樣做:
varunwrappedAuthorName = authorName!print("作者是\(unwrappedAuthor)")
變量名后面的感嘆號告訴編譯器你想看到盒子里面,并且把值拿出來。這是結(jié)果:
作者是張嘉夫
很棒!這就是你想要的。
使用詞語“強制”和感嘆號 ! 應(yīng)該給你傳達了一種危險感覺,這值得注意。你應(yīng)該盡量少的使用強制拆包。要知道為什么,考慮一下如果可選值不包含值得時候會發(fā)生什么:
authorName =nilvarunwrappedAuthorName = authorName!print("作者是\(unwrappedAuthorName)")
這個代碼產(chǎn)生了如下運行時錯誤:
fatal error: unexpectedly foundnilwhileunwrapping an Optional value(致命錯誤:未料到地,拆包一個可選值的時候發(fā)現(xiàn)是nil)
發(fā)生了這個錯誤是因為在你嘗試拆包變量的時候它沒有包含任何值。糟糕的是你是在運行時得到這個錯誤,而不是編譯時,意味著只有在用非法的輸入執(zhí)行這部分代碼的時候才會發(fā)生,你才能注意到它。更糟糕的是,如果這個代碼在一個 app 內(nèi)部,運行時錯誤會導致 app 崩潰!
怎么才能讓它安全呢?
要在這里停止運行時錯誤,你可以包住代碼,然后用一個檢查來拆包可選值,像這樣:
ifauthorName !=nil{varunwrappedAuthorName = authorName!print("作者是\(unwrappedAuthorName)")}else{print("沒有作者。")}
if 語句檢查可選值是不是包含 nil。如果不是,意味著它包含一個你可以拆包的值。
這個代碼現(xiàn)在安全了,但仍不失最佳狀態(tài)。如果你依賴這個技術(shù),每次你想拆包可選值的時候都要記住檢查 nil。這會開始變得單調(diào)乏味,有一天你會忘記,然后再次導致運行時錯誤的可能性。
然后回到繪圖板!
If let 綁定
幸運的是,Swift 包含了一個叫做if let 綁定(binding)的特色,讓你可以安全的訪問可選值里面的值。像這樣使用:
ifletunwrappedAuthorName:String= authorName {print("作者是\(unwrappedAuthorName)")}else{print("沒有作者。")}
你會立馬注意到這次沒有感嘆號了,并且 unwrappedAuthorName 的類型是一個普通的 String,不是一個可選值 String。
**注意:**一般的不會在 if let 語句指定拆包變量的類型,這里是為了顯示清楚。
這個特殊語法擺脫了可選值類型。如果可選值包含值,代碼執(zhí)行 if 語句的 if 那邊,自動拆包 unwrappedAuthorName 變量,因為你知道這是安全的,可以這么做。
如果可選值不包含值,代碼執(zhí)行 if 語句的 else 那邊。這個例子里,unwrappedAuthorName 甚至都不存在。
你可以看到 if let 綁定與強制拆包相比有多么安全,你應(yīng)該任何可能的時候選擇它。
你甚至可以一次拆包多個值,像這樣:
letauthorName:String? ="張嘉夫"letauthorAge:Int? =23ifletname:String= authorName,? ? age:Int= authorAge {print("作者是\(age)歲的\(name)。")}else{print("沒有作者或沒有年齡。")}
這段代碼拆包了兩個值。它只在兩個可選值都包含值得時候才會執(zhí)行 if 部分的語句。
現(xiàn)在你知道如何安全的看進一個可選值里面,并且取出值,如果有的話。
迷你練習
使用之前的 myFavoriteSong 變量,使用 if let 綁定來檢查是否包含值。如果是,print 這個值。如果沒有,print “我沒有一首喜歡的音樂。”
把 myFavoriteSong 設(shè)置為當前的相反面;也就是說,如果是 nil,就設(shè)置為一個字符串,如果是一個字符串,就設(shè)置為 nil。觀察你 print 的結(jié)果會有什么變化。
Nil 合并
有一個終極和更常用的方式來拆包可選值。當你想要取出可選值里的值,不論值是什么,就用它—如果是 nil,就會使用一個默認值。這叫做nil 合并(coalescing)。
這是它工作的方式:
varoptionalInt:Int? =10varresult:Int= optionalInt ??0
nil 合并發(fā)生在第二行,帶有兩個問號(??)。這行表示 result 會等于 optionalInt 里的值,或者如果 optionalInt 包含的是 nil 就等于 0。
所以這個例子里,result 包含具體的 Int 值 10。
上面的代碼和下面等同:
varoptionalInt: Int? =10varresult: Intifletunwrapped = optionalInt {? ? result = unwrapped}else{? ? result =0}
設(shè)置 optionalInt 為 nil,像這樣:
optionalInt =nilvarresult:Int= optionalInt ??0
現(xiàn)在你的 result 等于 0。
關(guān)鍵點
Nil表示值的缺失。
非可選值變量和常量一定會有一個非 nil 值。
可選值(Optional)變量和常量就像盒子,可以包含一個值或是空的(nil)。
要處理可選值里的值,首先必須從可選值里拆包。
拆包可選值最安全的方式是使用if let 綁定(binding)或nil 合并。避免強制拆包(forced unwrapping),它可能會導致一個運行時錯誤。
接下來去哪兒?
這就是可選值啦,Swift 的一個核心特色,幫助讓語言更安全,使用起來更簡單。你會發(fā)現(xiàn)代碼里會貫穿始終使用使用它們。他們幫你讓代碼更安全,通過保證明確處理值的缺失情況。在你的 Swift 體驗中,你應(yīng)該會越來越欣賞它。
特別是,你會在 10-12 篇教程中使用它們,并且在那里學習集合(collections)。
挑戰(zhàn)
你已經(jīng)學習了可選值背后的理論,并且在實踐中見過他們了?,F(xiàn)在輪到你搞一下了!
挑戰(zhàn) A:你就是編譯器
下列哪個是有效語句?
varname:String? ="嘉夫"varage:Int=nilletdistance:Float=26.7varmiddleName:String? =nil
挑戰(zhàn) B:分而治之
首先,創(chuàng)建一個函數(shù),返回一個整數(shù)可以被另一個整數(shù)整數(shù)的次數(shù)。如果不能整除就返回 nil。命名函數(shù)為 divideIfWhole。
然后,寫代碼嘗試拆包函數(shù)的可選值結(jié)果。應(yīng)該有兩種情況:如果成功,print “Yep, 它整除 (answer) 次”,如果失敗,print “除不盡 :[”。
最后,測試你的函數(shù):
10 除以 2。應(yīng)該 print “Yep,它整除 5 次?!?/p>
10 除以 3。應(yīng)該 print “除不盡 :[”
提示 1:使用如下作為函數(shù)構(gòu)造的開始:
funcdivideIfWhole(value: Int, by divisor: Int)
你需要添加返回類型,這應(yīng)該是一個可選值!
提示 2:你可以使用模除操作符(%)來決定一個值是否能被另一個除盡;回想一下,這個操作返回兩個數(shù)字相除的余數(shù)。例如,10 % 2 = 0 意味著 10 可以被 0 除盡,沒有余數(shù),但是 10 % 3 = 1 意味著 10 被 3 除了三次,有一個余數(shù)為 1。
挑戰(zhàn) C:重構(gòu)與改善
上一個挑戰(zhàn)里,你用 if 語句寫的代碼。在這個挑戰(zhàn)里,重構(gòu)代碼,使用 nil 合并。這次,所有情況都讓它輸出 “它除了 X 次”,但如果不是整除,那 X 就應(yīng)該是 0。
挑戰(zhàn)和迷你練習源代碼
https://yunpan.cn/cBDRwNvgpHy4G(提取碼:f961)
介紹
歡迎來到Swift世界!Swift是一門蘋果在2014年夏天發(fā)布的編程語言。從那之后,Swift發(fā)布了一個主要的版本跳躍,成為了開始在蘋果平臺:iOS,OS X,watchOS和tvOS開發(fā)的最簡單的方式。
誰適合這篇教程
這篇教程適合懂一點編程、并且希望學習Swift的人。也許你已經(jīng)為網(wǎng)站寫過一些JavaScript代碼,或者用Python寫過一些簡短的程序。這篇教程就是為你準備的!你會學習到編程的基本概念,同時也會成為Swift語言小能手。
如果你是赤裸裸的編程新手,這篇教程也是為你準備的!教程里貫穿有簡短的鍛煉和挑戰(zhàn)來給你一些編程練習,同時測試你的知識。
需要準備什么
要看這篇教程,你需要準備如下的東西:
一臺運行OS X El Captian(10.11)的Mac,帶有最新發(fā)布的更新并且安裝了安全補丁。這樣你才能夠安裝需要的開發(fā)工具:最新版本的Xcode。
Xcode 7.3 或更新的版本。Xcode是用Swift寫代碼的主要開發(fā)工具。最小也需要Xcode 7.3版本,因為那個版本包含Swift 2.2。你可以免費從Mac App Store下載Xcode的最新版本,這里:http://apple.co/1FLn51R。
如果你還沒有安裝Xcode最新版本,在繼續(xù)看下面的教程前要確定安裝。
如何使用這篇教程
每篇教程都會介紹觸手可及的話題理論,伴隨大量Swift代碼來示范在學習的實際的應(yīng)用程序。
教程里的所有代碼都是平臺中立的;這意味著不是為iOS、OS X或任何其它平臺而特定。代碼在playgrounds里運行,你在本篇中已經(jīng)學習了。
在剩下的教程里,你可以把代碼在自己的playground里輸入進去。這樣你就可以和代碼“玩耍”(play around),做一些改變立即就能看見代碼運行的結(jié)果。
剩下的教程里會貫穿實際小練習,都是簡短的練習,關(guān)于觸手可及的主題。每篇的末尾也有挑戰(zhàn),會有編程問題也會有長一點的代碼練習來測試你的知識。做完就能掌握大部分的Swift基礎(chǔ)知識。
教程更新
教程會隨Swift語言的更新而更新,會發(fā)布在我的簡書和知乎專欄上,搜索“張嘉夫”即可關(guān)注我。
目錄
本教程從一些基礎(chǔ)工作開始來讓你起步:
第1篇,編程本質(zhì) & Playground基礎(chǔ)- 這就是,到編程世界的入門介紹!你會從電腦和編程的預(yù)覽開始,然后剩余時間給Swift playground打個招呼。
第2篇,變量 & 常量- 你會學習到變量和常量,這是用來存儲數(shù)據(jù)的“地方”。你也會學習數(shù)據(jù)類型以及Swift如何追蹤數(shù)據(jù)類型并在代碼中進行傳輸。
第3篇,數(shù)字類型 & 操作- 你會從基礎(chǔ)的數(shù)字類型比如整形和浮點型數(shù)字開始,當然也包括布爾類型。也會看到一些在實際操作,從比較到算數(shù)操作如加減。
第4篇,字符串- 用字符串來存儲文字-從按鈕里的文字到圖片的標注到這篇教程全部的文字,存儲這所有的一切!你會學習到string和character類型,以及基于這些類型的一些常見操作。
在腦海中有基礎(chǔ)數(shù)據(jù)類型后,就該用那些數(shù)據(jù)做一些事情了:
第5篇,做判斷- 代碼不總是直接從頭運行到尾。你會學習在代碼里如何做判決并且設(shè)定情況來運行某段代碼。
第6篇,重復(fù)步驟- 繼續(xù)不要讓代碼直線運行的主題,你會學習到如何使用循環(huán)來重復(fù)某些步驟。
第7篇,函數(shù)- 函數(shù)是Swift中用來構(gòu)建代碼的基礎(chǔ)建筑。你會學習到如何定義函數(shù)來分組代碼到可復(fù)用單元中。
第8篇,閉包(Closures)- 閉包和函數(shù)很接近。你會學習到如何使用它們來輕松傳遞代碼塊。
最后一篇會回到數(shù)據(jù):
第9節(jié),可選值- 這篇講可選值,Swift中的一種特殊類型,表示既有可能是一個真實的值也有可能沒有值。這篇的最后你會知道為什么要用可選值以及如何安全地使用它們。
這些基礎(chǔ)會讓你快速開始Swift之路,做好接觸更高級編程主題的準備。
文/張嘉夫(簡書作者)
原文鏈接:http://www.lxweimin.com/p/684413b2cfbb#
著作權(quán)歸作者所有,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),并標注“簡書作者”。