Swift:面向協(xié)議編程_第1頁
Swift:面向協(xié)議編程_第2頁
Swift:面向協(xié)議編程_第3頁
Swift:面向協(xié)議編程_第4頁
Swift:面向協(xié)議編程_第5頁
已閱讀5頁,還剩162頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領

文檔簡介

Swift面向協(xié)議編程注:因內(nèi)容過長上傳受限制,本文檔只顯示部分內(nèi)容,完整版文檔請下載此文檔后留言謝謝。目錄\h第1章搭建Swift開發(fā)環(huán)境\h1.1Swift介紹\h1.1.1Swift的前世今生\h1.1.2Swift與Objective-C\h1.2MacOSX操作系統(tǒng)\h1.3Xcode簡介和獲取方法\h1.3.1Xcode簡介\h1.3.2playground簡介\h1.3.3Xcode的獲取方法\h1.4iPhoneSDK簡介\h第2章Swift基礎語法\h2.1基礎知識\h2.1.1命名規(guī)則\h2.1.2常量與變量\h2.1.3類型推測\h2.1.4注釋\h2.1.5輸出常量和變量\h2.2基本數(shù)據(jù)類型\h2.2.1整數(shù)\h2.2.2浮點數(shù)\h2.2.3布爾類型\h2.2.4元組類型\h2.2.5可選型\h2.3基本運算符\h2.3.1賦值運算符\h2.3.2數(shù)值運算\h2.3.3自增和自減運算\h2.3.4復合賦值\h2.3.5比較運算\h2.3.6三元運算符\h2.3.7邏輯運算符\h2.3.8范圍\h2.3.9括號優(yōu)先級\h2.4字符串與字符\h2.5集合類型\h2.5.1數(shù)組\h2.5.2集合\h2.5.3字典\h2.6控制流\h2.6.1for循環(huán)\h2.6.2while循環(huán)\h2.6.3if判斷語句\h2.6.4guard判斷語句\h2.6.5switch開關語句\h2.7函數(shù)\h2.8閉包\h2.9Swift三杰——類、結(jié)構(gòu)體、枚舉\h2.9.1Swift三杰簡介\h2.9.2值引用與類型引用\h2.9.3類\h2.9.4結(jié)構(gòu)體\h2.9.5枚舉\h2.10屬性\h2.10.1存儲屬性\h2.10.2計算屬性\h2.10.3屬性觀察器\h2.10.4類型屬性\h2.11方法\h2.12下標\h2.13繼承\(zhòng)h2.14構(gòu)造與析構(gòu)\h2.14.1構(gòu)造器\h2.14.2析構(gòu)器\h2.15類型檢查與類型轉(zhuǎn)換\h2.15.1類型檢查\h2.15.2類型轉(zhuǎn)換\h2.16類型嵌套\h2.17擴展\h2.17.1擴展計算屬性\h2.17.2擴展構(gòu)造器\h2.17.3擴展方法\h2.17.4擴展下標\h2.18協(xié)議\h2.18.1聲明協(xié)議\h2.18.2遵守協(xié)議\h2.18.3實現(xiàn)協(xié)議\h2.18.4實現(xiàn)擴展\h2.18.5協(xié)議擴展補充\h2.18.6協(xié)議的繼承\(zhòng)h2.19泛型\h2.19.1節(jié)點泛型\h2.19.2泛型協(xié)議\h2.19.3泛型對象\h2.19.4泛型方法\h2.19.5協(xié)議中的where關鍵字\h2.19.6泛型特化\h2.20Swift語法補充\h2.20.1斷言\h2.20.2precondition\h第3章Swift進階語法\h3.1再談可選型\h3.1.1可選型\h3.1.2為什么要用可選型\h3.1.3解包可選型\h3.1.4可選綁定\h3.1.5可選鏈\h3.1.6可選型中的map和flatMap\h3.1.7Swift中的錯誤處理\h3.1.8隱式解包\h3.1.9關于可選型的思考\h3.2同構(gòu)與異構(gòu)\h3.2.1數(shù)據(jù)源中的同構(gòu)與異構(gòu)\h3.2.2AnyObject/Any簡介\h3.2.3AnyObject的使用\h3.2.4AnyObject與id的對比\h3.3數(shù)組方法的探究\h3.3.1filter方法\h3.3.2map和flatMap方法\h3.3.3reduce方法\h3.3.4sort(sorted)方法\h3.3.5Side-Effect與forEach方法\h3.3.6contains方法\h3.3.7indexOf(index(of:))方法\h3.3.8prefix、suffix系方法\h3.3.9dropFirst、dropLast方法\h3.3.10Slice\h3.3.11RangeReplaceableCollectionType\h3.3.12數(shù)組的底層協(xié)議\h3.3.13帶下標的數(shù)組遍歷\h3.3.14Demo演示\h3.4Objective-C兼容性\h3.4.1類型橋接\h3.4.2OC和Swift的設計區(qū)別\h3.5Swift內(nèi)存管理\h3.5.1棧和堆\h3.5.2值類型和引用類型\h3.5.3Copy-on-Write\h3.5.4利用引用類型的“共享”\h3.5.5ARC(自動引用計數(shù))\h3.5.6循環(huán)引用\h3.5.7弱引用與無主引用\h3.5.8柯里化與方法參數(shù)中的閉包\h3.5.9@noescape與@autoclosure\h3.5.10靜態(tài)派發(fā)和動態(tài)派發(fā)\h3.5.11協(xié)議類型的存儲屬性\h3.5.12靜態(tài)多態(tài)與動態(tài)多態(tài)\h3.5.13泛型特化\h3.5.14小結(jié)\h3.6模式匹配\h3.6.1模式匹配簡介\h3.6.2枚舉的模式匹配\h3.6.3元組的模式匹配\h3.6.4if和guard中的模式匹配\h3.6.5for中的模式匹配\h3.6.6模式匹配中的where關鍵字\h第4章iOS開發(fā)入門\h4.1iOS系統(tǒng)初探\h4.1.1核心OS(CoreOS)層\h4.1.2核心服務(CoreServices)層\h4.1.3媒體(Media)層\h4.1.4CocoaTouch層\h4.2MVC模式\h4.2.1MVC簡介\h4.2.2iOS中的MVC\h4.3新建一個Swift工程\h4.4認識InterfaceBuilder\h4.5構(gòu)建計算器界面\h4.5.1使用對象庫中的對象\h4.5.2使用檢查器設置對象\h4.5.3嘗試運行程序\h4.5.4添加約束\h4.5.5關聯(lián)代碼\h4.5.6完善按鍵\h4.6實現(xiàn)計算器邏輯\h4.6.1補全鍵盤\h4.6.2給鍵盤添加約束\h4.6.3實現(xiàn)數(shù)字顯示功能\h4.6.4實現(xiàn)運算邏輯\h4.7修改計算器為MVC模式\h4.8NSNotification\h4.8.1NSNotification簡介\h4.8.2addObserver方法\h4.8.3addObserverForName方法\h4.8.4postNotification方法\h4.8.5Swift3.0中的Notification\h4.9AutoLayout快速入門\h4.9.1邊距與距離\h4.9.2中心與對齊\h4.9.3尺寸與比例\h4.9.4絕對位置與擠壓\h第5章面向協(xié)議編程\h5.1繼承與組合\h5.2搭建頁面\h5.3創(chuàng)建storyboard對應的子類\h5.4創(chuàng)建模型\h5.5串聯(lián)MVC\h5.6MVVM\h5.7圖解MVC與MVVM\h5.8MVC面向協(xié)議化\h5.9MVC多態(tài)優(yōu)化\h5.10快速開發(fā)\h5.11組合\h5.12交互\h5.13搜索第1章

搭建Swift開發(fā)環(huán)境正所謂“工欲善其事,必先利其器”,在開始學習Swift之前,我們需要做好相關的準備。由于Swift是蘋果公司的“親兒子”,所以你可以在Mac上快速開啟你的Swift之旅,本書使用的開發(fā)工具是蘋果的Xcode。1.1Swift介紹1.1.1Swift的前世今生在閱讀本書之前,可能你已經(jīng)從其他渠道了解了一些Swift的相關信息,下面簡單介紹一下Swift語言的前世今生。作為編程語言界的“小鮮肉”,Swift是蘋果公司在2014年WWDC(蘋果全球開發(fā)者大會)上發(fā)布的全新的編程語言。Swift是供iOS和OSX應用編程的新編程語言,基于C和Objective-C,沒有C的一些兼容約束。Swift采用了安全的編程模式,并添加新的功能,以使得編程更加簡單、靈活、有趣。界面則基于深受廣大碼民喜愛的Cocoa和CocoaTouch框架,展示了軟件開發(fā)的新方向。有人笑言Swift語言是語言進化鏈頂端的語言,因為它融合了很多現(xiàn)代編程語言的優(yōu)點,加入了諸如閉包這樣的高級語言特性。在語法結(jié)構(gòu)上,Swift有點類似于JavaScript這樣的腳本語言,但更加簡潔優(yōu)雅。2010年7月,LLVM編譯器的原作者,暨蘋果開發(fā)者工具部門總監(jiān)克里斯·拉特納(ChrisLattner)開始著手Swift編程語言的工作,還有一個Dogfooding團隊大力參與其中。至2014年6月發(fā)表時,Swift歷經(jīng)了大約4年的開發(fā)期??死锼乖陂_發(fā)Swift之前的一項偉大成就是為蘋果公司開發(fā)了LLVM編譯框架。由于他在編譯框架方面的豐富經(jīng)驗,使得Swift不但語法簡潔,而且對編譯期的速度也有所優(yōu)化,讀者在使用Swift進行開發(fā)時一定深有感觸。開源之后,Swift得到了更多開發(fā)者的青睞,在最近幾個月的Tiobe世界編程語言排行榜上,Swift都反超了Objective-C,排名穩(wěn)中有升,2016年8月的Tiobe世界編程語言排行榜如圖1.1所示。圖1.12016年8月的Tiobe世界編程語言排行榜1.1.2Swift與Objective-C我們知道,以前進行iOS開發(fā)時使用的是Objective-C(以下簡稱OC)這門古老的語言,Swift語言的發(fā)布對于熟悉OC開發(fā)的程序員來說是一件令人興奮的事情。因為OC是C語言的超集,比較像C++這樣的傳統(tǒng)面向?qū)ο笳Z言,而沒有很多現(xiàn)代高級語言的特性。并且由于OC是一門消息傳遞語言,而不是傳統(tǒng)的函數(shù)調(diào)用語言,因此OC里面中的括號語法使得很多從其他編程語言轉(zhuǎn)投OC開發(fā)的程序員很不適應。但是這并不代表OC不好。任何一門新興的語言都在不斷變化之中,由于Swift的發(fā)布時間較短,而筆者學習Swift語言的時候還處在Swift語言的元年,筆者的學習過程跨越了Swift1.1版本到Swift3版本,語法有很多變動。如果你正在維護一個大型項目,那么語法的變動肯定是你不想看到的。所幸蘋果承諾3.0版本將是Swift最后一個“破壞性”升級的版本。對于有志于從事iOS開發(fā)工作或者是服務端開發(fā)的讀者,使用Swift可能是一件“當下痛苦,未來愉悅”的事情。本書在介紹Swift語法時也會穿插OC中的一些代碼做對比,讓讀者更加了解兩種語言的差異。最后,筆者建議在學習Swift語言的同時,應熟悉OC語言,兩件兵器同時在手,笑傲職場,豈不更加游刃有余!1.2MacOSX操作系統(tǒng)OSX是蘋果公司為Mac系列產(chǎn)品開發(fā)的專屬操作系統(tǒng)(新版本已經(jīng)正式更名為MacOS了),基于UNIX系統(tǒng),有一定Linux基礎的人使用OSX時會更加得心應手。OSX操作系統(tǒng)的獲取方式有兩種,最簡單的一種是買一臺蘋果電腦,無論是哪個系列,這些電腦都預裝了OSX操作系統(tǒng)。如果你不打算購買蘋果電腦,另外一種方式是在Windows環(huán)境下用虛擬機安裝OSX操作系統(tǒng),也就是我們通常所說的“黑蘋果”,網(wǎng)上有詳細的教程,筆者在此不做過多的介紹。但需要強調(diào)的是,“黑蘋果”下的開發(fā)有著各種各樣的問題,會拖累我們的學習進度,如果你只是想嘗嘗鮮,了解一下Swift語言,那么你大可不必購買一臺真正的蘋果電腦。但是對于一個有志于在現(xiàn)在或者將來進行iOS系統(tǒng)開發(fā)的讀者來說,一臺真正的蘋果電腦是必不可少的;因為不僅企業(yè)中的iOS開發(fā)全部是在蘋果電腦上進行的,甚至一些其他領域的開發(fā)也會選擇蘋果電腦,而蘋果電腦的易用性和良好的操控性可以大大提升你的編程舒適度。1.3Xcode簡介和獲取方法1.3.1Xcode簡介Xcode是蘋果推出的編程工具,必須安裝在MacOSX系統(tǒng)上,Xcode7.3.1要求OSX的版本不低于10.11。Xcode7的啟動界面如圖1.2所示,本書所展示的示例代碼全部使用正式版本的Xcode進行編寫。2015年9月,Xcode7正式版發(fā)布,Swift語言進入2.X時代,Xcode7.3.1中使用的Swift語言版本是2.2版本。圖1.2Xcode7啟動界面從圖1.2可以看到,啟動Xcode后,左側(cè)可以選擇新建一個playground文件、一個Xcode工程或者檢查一個已經(jīng)存在的項目,右側(cè)可以顯示使用Xcode打開的工程或者文件的歷史記錄。本書前幾章主要介紹Swift的語法,筆者推薦大家使用playground進行Swift語言的學習。1.3.2playground簡介playground是隨著Swift在蘋果的2014WWDC上發(fā)布的,只有在Xcode6之后的版本中才能看到它的身影。Xcode的playground功能是Swift為蘋果開發(fā)工具帶來的最大創(chuàng)新。該功能提供了強大的互動效果,能讓Swift源代碼在撰寫過程中實時顯示其運行結(jié)果,避免了編譯運行的耗時,大大提高了學習效率。我們只需在Xcode啟動界面的左側(cè)單擊第一個條目就可以創(chuàng)建一個playground,如圖1.3所示。圖1.3創(chuàng)建一個Playground之后給新建的文件取名并選擇保存路徑,playground的界面就展示在我們面前了。如圖1.4所示。新的playground中會有一些默認的代碼,可以看到界面分為左右兩部分,左側(cè)是代碼,右側(cè)是代碼結(jié)果的實時展示,簡單易用。

注意:代碼第三行“importUIKit”中的import關鍵字的作用是向Swift中導入框架,UIKit框架包含了頁面開發(fā)中的各種組件,我們會在后面的章節(jié)詳細介紹UIKit中各個組件的用法。圖1.4playground界面展示1.3.3Xcode的獲取方法用戶可以通過蘋果的官方商店下載Xcode,商店中的Xcode是正式版本,筆者推薦大家使用穩(wěn)定版本,而不要使用測試版本。需要注意的是,在蘋果商店中下載軟件時需要有APPID,如果沒有,可以免費注冊一個。如圖1.5所示,打開蘋果商店,在右上角的搜索框中輸入“Xcode”,就可以找到Xcode并安裝它了。圖1.5在蘋果商店中搜索Xcode如果想要嘗試測試版本的Xcode,則通過蘋果的開發(fā)者網(wǎng)站就可以找到,只不過下載時需要蘋果的開發(fā)者賬號。當然,每次公布測試版本的Xcode之后,網(wǎng)上都有很多人共享,即便你沒有開發(fā)者賬號也可以從他們提供的網(wǎng)盤鏈接中下載。1.4iPhoneSDK簡介iPhoneSDK是蘋果公司提供的iPhone開發(fā)工具包,包括界面開發(fā)工具、集成開發(fā)工具、框架工具、編譯器、分析工具、開發(fā)樣本和一個模擬器。在早些年的iOS開發(fā)中,我們需要手動安裝iPhoneSDK,現(xiàn)在Xcode中已經(jīng)集成了iPhoneSDK,我們無須自己再去配置它。隨著Xcode版本的升級,其集成的iPhoneSDK版本也會升級,比如Xcode7.3版本的iPhoneSDK版本號是9.3。需要注意的是,在真機測試時,Xcode中需要包含真機上的系統(tǒng)版本所對應的iPhoneSDK。第2章

Swift基礎語法相信通過第1章的介紹,你已經(jīng)迫不及待地想要在Swift的舞臺上大展身手了。在本章,你將正式接觸到Swift的語法。本書盡可能詳盡地從用法與原理上解讀Swift的語法,遇到不易理解的地方希望讀者可以細細揣摩,夯實語法基礎。為了突出Swift與Objective-C的區(qū)別,在介紹Swift語法時,會展示一些簡單的OC語法作為對比;即便之前沒有接觸過OC語法,只要你有一定的編程基礎,就能輕松看懂。本章絕大多數(shù)代碼都在playground中進行演示。2.1基礎知識2.1.1命名規(guī)則在Swift中,我們所定義的變量、常量、類或者方法都需要有各自的名稱,名稱是區(qū)分它們的唯一標識。如果你使用相同的名稱重復定義,那么就會收到系統(tǒng)的報錯提示。這里所說的名稱在計算機語言中的標準稱呼是標識符。標識符的構(gòu)成有一定的規(guī)范:標識符中大小寫代表不同的含義,所以XIAOMING和xiaoming代表兩個不同的標識符。不能包含數(shù)學符號、箭頭、保留的Unicode碼位、連線符與制表符。可以包含數(shù)字,但是數(shù)字不能作為標識符的首字符。不能使用Swift保留的關鍵字作為標識符(雖然Proposal0071中表示關鍵字已經(jīng)可以被用作標識符了,但是Swift3.0正式版中仍舊無法使用)。值得注意的是,Swift的標識符可以使用中文命名,或許你已經(jīng)習慣了用abc來命名變量,使用i和j來保存循環(huán)的次數(shù),但現(xiàn)在你可以使用諸如“重量”、“數(shù)量”這樣的中文來作為標識符。這得益于Swift中的字母采用的是Unicode編碼,Unicode的中文翻譯是統(tǒng)一編碼制,其中不僅有英文,還有亞洲文字,甚至我們常用的表情“”也在Unicode編碼之中,所以如果你夠任性,甚至可以使用一個笑臉來作為變量名。Swift中類、協(xié)議、結(jié)構(gòu)體、枚舉的標識符中的第一個字符通常要大寫,而方法的標識符中第一個字母通常為小寫,以示區(qū)分。另外,標識符整體的命名采用“駝峰式”的命名規(guī)則,即如果標識符由多個單詞組成,那么標識符的首字母遵從上面的命名規(guī)則,而其他單詞的首字母全部大寫,比如maxNumberOfArray,整個標識符中的多個單詞通過大寫的首字母做出了清晰地劃分,看起來就像是駱駝的駝峰一樣,避免了使用下畫線“_”來分隔單詞。良好的命名習慣,可以極大地提升代碼的可讀性,僅通過標識符的名稱就可以清晰地表達出代碼的含義。2.1.2常量與變量在OC中,常量與變量的劃分有時與具體的類型綁定。比如,變量字符串使用NSMutableString定義,常量字符串使用NSString定義。再如,可變數(shù)組使用NSMutableArray定義,而不可變數(shù)組使用NSArray定義。Swift語言消除了這種命名上的冗余性,常量和變量定義變得非常簡單。如果要定義一個常量,則使用let關鍵字定義;如果要定義一個變量,則使用var關鍵字定義。無論你想定義的是整型、浮點型、數(shù)組還是字符串,都只需使用這兩個關鍵字來進行區(qū)分。例如下面的代碼:

letname="

教科書的靈魂小明同學

"http://

使用

let

關鍵字定義了一個常量

name

varhisAge=8//

使用

var

關鍵字定義了一個變量

hisAge

上面的語句可以理解成兩步,首先通過let和var定義了一個常量和變量,然后使用“=”初始化這個常量和變量。變量的值可以在后面的代碼中通過賦值語句進行修改,而常量的值一旦設定將不能更改。

name="

了不起的李雷

"http://

程序會報錯,提示你不能修改常量

hisAge=15//

年齡是個變量,所以修改年齡沒有問題

Swift的開發(fā)原則是盡量使用常量,因為常量的運行效率更高。如果你定義的變量在代碼中沒有發(fā)生改變,那么編譯器會提示你把變量修改成常量。看完上面的代碼,你可能注意到了,每一行代碼的末尾都沒有使用“;”。這并不是筆者粗心大意漏掉了。在初學C語言的時候,你可能因為漏掉了“;”而吃了不少苦,但在Swift中,我們可以徹底和分號說拜拜了。在一行完整的語句結(jié)束后,我們只需換行即可;當然,在代碼的末尾寫上“;”也完全沒有問題。比如,下面的兩種寫法是等價的,只不過在實際編程中,通過換行的方式來分隔代碼效率會更高。

varcar="

奧迪

"

varcar="

奧迪

";

2.1.3類型推測在之前的代碼中,除“分號”的使用外,另外一個令人疑惑的地方是,我們在定義一個常量或者變量的時候,并沒有指定它的類型,這樣的寫法在playground中卻沒有報錯,這似乎有些不合常理。因為在OC中聲明一個變量時,必須要指定它的數(shù)據(jù)類型,例如:

constintcount=10;

doubleprice=9.9;

NSString*message=@"ThisisObjective-C";

你可能會覺得Swift不是一門強類型語言,然而事實恰恰相反,Swift是一門不折不扣的強類型語言。在聲明變量時,不需要指定數(shù)據(jù)類型的特性依托于Swift強大的類型推測功能。在Swift中,聲明的常量和變量可以通過在初始化時判斷傳遞給它的具體值的類型,并把這個類型作為常量和變量的類型,如以下代碼所示:

letcount=10

//count

會被識別為

Int

varprice=9.9

//price

會被識別為

Double

varmessage="ThisisSwift"

//message

會被識別為

String

當然,你也可以在聲明時顯式地指定常量和變量的數(shù)值類型:

varname:String="

小明

"http://

在聲明時指定

name

的數(shù)據(jù)類型

Swift是一門類型安全的語言,無論你是顯式地聲明類型,還是更習慣讓系統(tǒng)去做類型推測,每個常量和變量的類型都是明確的;Swift會在編譯期檢查所有的類型,以保證系統(tǒng)在運行期安全無誤,你永遠不能給一個Int類型的常量或變量傳入一個String類型的值。2.1.4注釋有編程經(jīng)驗的讀者對注釋肯定不會陌生,注釋一方面可以幫助我們更好地解釋代碼,另一方面還可以通過注釋具體的代碼段起到調(diào)試程序的作用。Swift中的注釋和其他語言中的注釋功能基本一致。注釋分為單行注釋和塊注釋。單行注釋在上面的代碼中已經(jīng)使用了很多次,在單行代碼的末尾使用//作為注釋的起點,后面的文字均為注釋,注釋不會對代碼的執(zhí)行產(chǎn)生任何影響。如果需要注釋的內(nèi)容比較多,那么需要使用塊注釋,塊注釋使用/*作為起點,使用*/作為終點,起點與終點之間的內(nèi)容全部為注釋,不參與代碼的執(zhí)行,如下所示:

//

單行注釋格式

/*

塊注釋格式

*/

在Xcode中,選中需要注釋的內(nèi)容按下command+/鍵,可以快速注釋所選內(nèi)容;如果要取消注釋,則選中注釋的內(nèi)容,再次按下command+/鍵就可以取消注釋。在Xcode8中,需要在終端輸入sudo/usr/libexec/xpccachectl,然后重啟電腦才可以使用這個快捷鍵。2.1.5輸出常量和變量如果要把常量和變量的值輸出到中控臺,則應使用print函數(shù),這個函數(shù)是默認換行的,比如:

print("

"我愛

Swift!")//

如果是在

Xcode

的工程中

,“

我愛

Swift”

會顯示在中控臺

print(items:Any...)是默認換行的,參數(shù)items是可變參數(shù)。如果傳入多個參數(shù),則每個參數(shù)之間都會用一個空格隔開,比如下面的示例代碼:

print("1","2")

print("3","4")

打印結(jié)果是:1234你可以對items中的參數(shù)指定分隔符和終止符,即使用另一個重載的print方法:

print("a","b","c",separator:"*",terminator:"end")

打印結(jié)果是:a*b*cend

注意:帶有分隔符和終止符的print方法是不換行的,如果在上面的語句后面再加上一個普通的print:

print("a","b","c",separator:"*",terminator:"end")

print("111")

打印結(jié)果是:a*b*cend111Swift采用字符串插值的方式在輸出的內(nèi)容中加入常量或變量的值。首先將常量或變量名放入\()的括號中,然后將\(常量名)或者\(變量名)當作占位符插到字符串的相應位置,這樣print函數(shù)在輸出時就會在該位置插入常量或變量的值,代碼如下:

letname="

小明

"

print("

我同桌名叫

\(name)")

playground中的實際效果如圖2.1所示。圖2.1字符串插值這樣的輸出方式相比OC中使用的NSLog函數(shù)更加直觀,同樣的功能在OC中的寫法如下:

NSString*name=@"

小明

";

NSLog(@"

我同桌名叫

%@",name);

注意:在筆者看來,print更適用于在playground中調(diào)試代碼。在真正的工程中,代碼通常比較復雜,如果你想知道某個對象的值,則加入一個print語句之后需要重新編譯,會消耗很多時間成本。而且在程序運行時,編譯器不會過濾我們手寫的print,而這些print對用戶而言是沒有任何意義的,所以在工程中盡量不要寫print,養(yǎng)成打斷點的好習慣。2.2基本數(shù)據(jù)類型本節(jié)將介紹Swift中的幾大類基本數(shù)據(jù)類型,包括整數(shù)、浮點數(shù)、布爾型、可選型和元組,接著會展示數(shù)字類型之間的轉(zhuǎn)換。至于字符串、集合、結(jié)構(gòu)體、類等類型,由于內(nèi)容較多,因此將會放在后面單獨的章節(jié)中進行講解。需要注意的是,Swift中的數(shù)據(jù)類型雖然名稱和C語言中的數(shù)據(jù)類型相似,但是Swift中數(shù)據(jù)類型的首字母都是大寫的。2.2.1整數(shù)整數(shù)的定義為沒有小數(shù)部分的數(shù)字,可以帶有正負號。Swift提供了Int和UInt兩種整數(shù)類型,分別表示有符號和無符號的整數(shù)類型。另外Int和UInt后面可以帶有數(shù)字8、16、32和64,以表示8、16、32、64位的整數(shù)。一般來講,我們并不需要指定整數(shù)的長度,使用UInt的情況也很少,在開發(fā)中使用Int類型即可。Int和UInt都是可以自適應平臺的類型,所以不需要關心自己的系統(tǒng)是64位還是32位。另外,整數(shù)類型有屬性max和min,分別表示不同整數(shù)類型的最大值和最小值,在Swift中我們訪問屬性采用“點方法”。為了加深理解,請看圖2.2。圖2.2Int8與UInt8類型2.2.2浮點數(shù)浮點數(shù)是指有小數(shù)部分的數(shù)字,比如我們熟悉的圓周率π。浮點數(shù)類型比整數(shù)類型表示的范圍要大。Swift提供了兩種浮點數(shù)類型:Float和Double。Float表示32位浮點數(shù),而Double表示64位浮點數(shù)。選擇哪種類型的浮點數(shù)取決于你對精度的要求。2.2.3布爾類型Swift提供了一個非真即假的邏輯類型——布爾類型(Bool)。布爾類型有兩個布爾常量:true和false。我們可以使用類型推斷,給變量或者常量直接賦值為true或者false,這樣常量或者變量的類型就會被識別為布爾類型。布爾類型在編程中有非常重要的作用。需要注意的是,Swift中的布爾類型不同于OC中的BOOL類型,不再接受0代表false、1代表true的用法,如圖2.3所示。圖2.3Swift中“1”不能代表true2.2.4元組類型元組是Swift中一個非常好用的數(shù)據(jù)類型,它可以把多個值成員復合成一個值,并且這些成員的數(shù)據(jù)類型可以不同;把成員值放到一個括號中,以逗號分隔。我們可以使用元組來定義一些固定形式的信息,比如一個學生的身份信息:

letmessage=("

小明

",9,"

三年二班

")

這個元組類型就可以表達出一個三年級二班名叫小明的9歲同學,結(jié)構(gòu)非常精簡。上面的代碼在playground中的顯示如圖2.4所示。圖2.4一個包含三個成員值的元組在右側(cè)的輸出頁面上我們可以看到,元組中每個成員值的前面都顯示了一個默認的索引,我們可以通過索引直接獲得元組中各部分的值,如圖2.5所示。圖2.5使用索引獲取元組成員的值我們也可以給每個成員變量命名,格式為(成員名稱1:成員值1,成員名稱2:成員值2,……),調(diào)用的時候可以使用名稱調(diào)用:

letmessage=(name:"

小明

",age:9,grade:"

三年二班

")

letshowName=

letshowAge=message.age

letshowGrade=message.grade

playground中的效果如圖2.6所示,可以看到其效果和使用索引是相同的。圖2.6使用元組成員名取值另外,如果想要獲取元組中的某些重要部分加以利用,忽略一些不重要的信息時,可以把元組的值傳遞到一個新的元組中;在新元組中聲明那些接受重要值的值成員,而不重要的部分使用下畫線“_”表示忽略。比如在上例中,只關心學生信息中的學生姓名,那么可以使用下面的語句,元組中的成員可以直接當作常量和變量使用:

letmessage=(name:"

小明

",age:9,grade:"

三年二班

")

let(showName,_,_)=message

print("Nameis\(showName)")

playground中的效果如圖2.7所示。圖2.7使用“_”忽略不重要的值2.2.5可選型OC中沒有可選型這種數(shù)據(jù)類型,可選型是Swift獨有的,初次接觸可選型時你可能有些許疑惑;但它是一種很精妙的數(shù)據(jù)類型,本章只做簡單介紹,第3章中將詳細介紹可選型的原理與作用??蛇x型用于某些不確定是否有值的情況,其有兩個返回值:具體的值和nil,nil表示空值。在Swift中,經(jīng)常會選擇可選型作為返回值來處理一些結(jié)果不確定的操作,定義可選型只需在常規(guī)類型后面加一個問號“?”即可,例如:

varage:Int?

這樣,age就被定義成一個可選型,如果它有值,就一定會返回一個Int類型的值,否則返回nil??蛇x型經(jīng)常被用作搜索或者轉(zhuǎn)型方法的返回值類型,這是因為在搜索和轉(zhuǎn)型中經(jīng)常出現(xiàn)失敗的情況,此時根據(jù)返回值就可以判斷流程是否成功。在Swift標準庫中有非常多這樣的設計,你可以參考這樣的設計準則。下面介紹一個轉(zhuǎn)型例子。在Swift中,String類型可以和Int類型的實例互相轉(zhuǎn)換,你可以把諸如“12”這樣的字符串轉(zhuǎn)換成Int,但是不能轉(zhuǎn)換“小明”這樣的字符串。Swift風格的轉(zhuǎn)型使用構(gòu)造器,這使得代碼更容易理解,構(gòu)造器的知識后面會具體講解,如圖2.8所示。圖2.8可選型使用示例值得注意的是,age在定義為Int類型的可選型之后被賦予了一個默認的初始值nil,這也是可選型的一個好處之一。Swift中的類和結(jié)構(gòu)體在初始化時其內(nèi)部的所有屬性必須被初始化,否則無法通過編譯,這也是出于安全性的考慮。把一個變量定義為可選型,在沒有賦值的情況下它會被默認賦值為nil;所以即便定義age的時候不賦值,它也已經(jīng)被初始化了,它的值是nil,直到你通過賦值更改它的值?,F(xiàn)在請看下面的代碼:

varage:Int?

age=Int("12")

print("ageis\(age)")

你可能認為代碼第三行輸出的應該是“ageis12”,但實際情況并不是這樣,如圖2.9所示。圖2.9未解包的可選型在輸出語句中我們得到age的值顯示為Optional(12),Optional代表“可選”,age的當前值為一個整數(shù)類型的可選型。在實際開發(fā)中我們真正需要的是括號中的12,要想獲取這個12,就需要使用“解包”操作。解包是針對于可選類型的變量操作,當我們確定一個可選型的值不為nil的時候,可以使用解包獲取其中的值。它的表現(xiàn)形式也很簡單,在需要進行解包的變量名后面加上一個感嘆號“!”。現(xiàn)在對age變量進行解包,效果如圖2.10所示。因為可選型對很多開發(fā)人員來說都是一個全新的概念,所以本書會在第3章中對可選型進行更深入的講解。圖2.10對可選型進行解包最后需要指出的是,聲明一個可選型雖然可以通過編譯器設置的安全性檢查,但是如果你不慎忘記在之后對其賦值,那么在解包的時候程序就會崩潰。即便你是個非常仔細的程序員,但是一旦聲明一個可選型就存在解包nil的可能性。聲明可選型會對我們的程序帶來風險,所以我們聲明一個對象的時候,尤其是聲明類或者結(jié)構(gòu)體的屬性的時候,應該三思而后行,盡可能為其賦初始值,當然這個初始值應該是明顯區(qū)別于正常值的。再把可選型轉(zhuǎn)換成非可選型的賦值語句中經(jīng)常用到“??”操作符,“??”之前為一個可選型,“??”之后為一個非可選型的值?!??”操作符自帶解包功能,在賦值時“??”會檢查其之前的可選型:如果可選型不為nil,則將其解包并返回;如果其為nil,則不會返回nil,此時返回“??”之后的非可選型的值。使用“??”改造上面的代碼,如下所示:

varage:Int//

這里避免解包,聲明age為非可選型

age=Int("12")??-1

print("ageis\(age)")//

轉(zhuǎn)型成功

age=Int("

小明

")??-1

print("ageis\(age)")//

轉(zhuǎn)型失敗

運行結(jié)果如圖2.11所示圖2.11“??”操作符由于在真實的數(shù)據(jù)環(huán)境中年齡不可能為負數(shù),此時當我們看到age為-1的時候就知道Int(String)轉(zhuǎn)型失敗了。相比于強制解包,Swift提供了一種更安全的解包方式:可選綁定??蛇x綁定有兩種格式可選:if-let和guard-let-else。首先來看if-let結(jié)構(gòu):

varage:Int?=Int("12")

ifleta=age{

print(a)

}

類似于if語句,當age不為空的時候,對age解包并給其一個“別名”a,在if后的大括號對中a才有效果,此時a的值為12,已經(jīng)解包了。如果age為nil,那么大括號對中的代碼不會執(zhí)行,使用可選解包程序不會崩潰。guard-let-else是Swift2.2新引入的格式,示例如下:

varage:Int?=Int("12")

funcfindA(){

guardleta=ageelse{

return//

終止方法

}

print(a)//

在外部使用解包后的值

}

不同于if-let,guard-let-else首先處理age為nil的情況,在此種情況中必須在大括號對中使用return或者break提前終止代碼。與if-let結(jié)構(gòu)相同的是,如果age有值,那么age的值也會被保存在“別名”a中;不同的是,不管有多少個guard-let-else,別名a的作用域都在最外層,有效地避免了過于深入的嵌套。2.3基本運算符本節(jié)將介紹Swift中的一些基本運算符,運算符是檢查、改變、合并值的特殊符號或短語。2.3.1賦值運算符之前在定義常量和變量時已經(jīng)接觸過賦值運算符的用法了,Swift使用等號“=”來表示賦值運算。例如a=b,表示將b的值賦給了a。如果賦值的對象是一個元組,那么元組內(nèi)成員的值在賦值操作中是一一對應的。比如let(x,y)=(1,2),則x的值會被賦為1,而y的值會被賦為2,依次類推。另外需要注意的一點是,如果你做過C語言的開發(fā),那么一定犯過這樣的錯誤,在判斷語句if中本該使用“==”進行判斷操作,但是誤寫成了“=”,造成了if判斷永真的情況。Swift為了避免這種情況發(fā)生,其賦值語句是沒有返回值的,也就是說,如果你使用如下語句:

ifx=y{}

系統(tǒng)會直接提示錯誤,避免開發(fā)人員犯設計性的錯誤。2.3.2數(shù)值運算Swift支持基本的加減乘除和求余運算,并且Swift中的數(shù)值運算與OC相比更加強大。比如Swift中的加法操作“+”除了可以用來對整數(shù)和浮點數(shù)做加法,還可以直接拼接字符串。Swift中的求余運算“%”可以對浮點數(shù)求余,這些都是C語言和OC所不具備的,示例代碼如圖2.12所示。圖2.12Swift中的數(shù)值運算2.3.3自增和自減運算為了幫助開發(fā)人員提前修改代碼以適應Swift語言的迭代,Swift3.0中確定將要發(fā)生的語法改變會在Swift2.2中以警告的形式出現(xiàn),自增自減就是其中之一。Swift2.2中仍舊可以使用“++”和“--”這樣C語言風格的操作符進行自加和自減的操作,但是這兩個操作符會在Swift3.0之后的版本中被刪除;所以為了避免不必要的麻煩,進行自加或自減應使用下面的寫法:

vara=1

a+=1//

自增

a-=1//

自減

相比于我們熟悉的“++”和“--”,上面的寫法還可以指定自增和自減的“步長”,從代碼風格統(tǒng)一的角度出發(fā),“++”和“--”確實顯得冗余了。2.3.4復合賦值Swift提供把運算符和賦值復合起來使用的復合操作,與自增和自減操作類似,a+=2的操作等同于a=a+2,示例代碼如圖2.13所示。圖2.13復合賦值操作2.3.5比較運算所有標準C中的比較運算符在Swift中都可以使用。另外,在Swift中,“==”可以用在任何類型的比較中,而不用像OC中那樣使用不同的isEqual方法。比較運算會返回Bool類型的比較結(jié)果。示例如圖2.14所示。圖2.14Swift中的比較運算2.3.6三元運算符前面展示的都是二元運算符,下面介紹三元運算符。不同于二元運算符的加減乘除,三元運算符有三個參與對象,格式為:判斷條件?為真時的操作:為假時的操作。它可以通過一個Bool類型判斷條件的真假來選擇執(zhí)行哪個操作,三元運算符是if-else結(jié)構(gòu)的一種簡化。比如下面的情況,小明有一個遠房王叔叔并不認識小明和他的哥哥小剛,但是王叔叔知道小明的身高不足160(cm),而小剛的身高要高于160(cm)。現(xiàn)在王叔叔見到了一個身高180(cm)的男孩,那么不需要自我介紹,王叔叔通過身高就可以判斷這個男孩是小剛而不是小明。這個判斷過程就對應了一個三元運算,如圖2.15所示。圖2.15三元運算符判斷過程2.3.7邏輯運算符Swift中的邏輯運算符的操作對象是布爾值。沿用了C語言中的三種邏輯運算:與、或、非。在工程中我們可以對布爾類型的篩選條件做邏輯運算來判斷代碼的執(zhí)行段。示例如圖2.16所示。圖2.16邏輯運算“邏輯與”運算使用“&&”符號表示,可以有多個條件同時參與運算,比如a&&b&&c……;只要其中有一個條件的布爾值為false,那么整個結(jié)果就為false,否則為true?!斑壿嫽颉边\算使用“||”符號表示,同樣可以有多個條件同時參與運算,比如a||b||c……;只要其中有一個條件的布爾值為true,那么整個結(jié)果就為true,否則為false。“邏輯非”運算使用“!”符號表示,非運算的結(jié)果總與“!”符號后面的布爾值相反。2.3.8范圍在OC中,我們可以使用Range函數(shù)來指示一個起始位置和長度,從而框定一個范圍。Swift中的范圍使用起來要方便得多,有兩種形式:1…5表示閉區(qū)間[1,5],也就是從1到5的范圍。1..<5表示半閉區(qū)間[1,5),也就是從1到4。范圍經(jīng)常會和for-in循環(huán)語句連用,比如下面的形式:

forindexin1...5

{

println(index)

}

也可以用在switch控制流的case中,在后面講到switch時會講解,基本形式如下:

varindex=3

switchindex{

case1...2:

print("Hello")

case3...4:

print("World")

default:break

}

2.3.9括號優(yōu)先級為了保持運算的先后順序,可以使用括號來指示優(yōu)先級。比如運算a*(b+c),雖然乘法的優(yōu)先級高于加法,但是由于使用了括號來指示優(yōu)先級,所以首先進行b+c的運算,然后其結(jié)果再與a相乘,與數(shù)學上的運算順序相同。除數(shù)值運算外,括號也可以用在邏輯運算中,比如a&&(b||c),表示首先進行括號中的或運算,然后其結(jié)果再與a做與運算。2.4字符串與字符在Swift中,字符串的類型是String,不論定義的是常量字符串還是變量字符串。

letdontModifyMe="

請不要修改我

"

varmodifyMe="

你可以修改我

"

而在OC中,你需要使用NSString和NSMutableString來區(qū)分字符串是否可以被修改。前面我們講過,在Swift中,連接兩個字符串組成新字符串非常方便,使用“+”即可,如圖2.17所示。圖2.17使用“+”拼接字符串在OC中我們要實現(xiàn)同樣的拼接只能使用stringWithFormat方法,做法如下:

NSString*firstMessage=@"Swift

很不錯

.";

NSString*secondMessage=@"

你覺得呢

?";

NSString*message=[NSStringstringWithFormat:@"%@%@",firstMessage,

secondMessage];

NSLog(@"%@",message);

在OC中,判斷兩個字符串是否相同時不能用“==”,而要使用方法isEqualToString,但在Swift中完全可以使用“==”來判斷字符串是否相同。

letstring1="Hello"

letstring2="Hello"

ifstring1==string2{

print("

二者相同

")

}

處理字符串的難點是字符串的索引和字符串的創(chuàng)建,以及如何創(chuàng)建一個字符串的子串。字符串由Unicode組成,但是不能把Unicode組成的字符串的子串看作Unicode字符,而是把它們拆分成Unicode字素。我們不能像在數(shù)組中那樣使用整數(shù)作為下標索引,因為會遇到有的字素是由多個字符組成的情況,這樣會把一個完整語義的字素拆成兩個字符,從而改變了原意。例如,法語中有重音符號,一個à是一個完整的字素,這個字素由兩個Unicode字符組成,如果按照Unicode字符來索引就會破壞語言的結(jié)構(gòu)。所以字符串是由另外的一個類型來索引的,這個類型就是String.Index。在Swift2.2中,想要獲得String中某個字素的時候,應使用函數(shù)advance;其中有兩個參數(shù),stratIndex指定String的第一個字素,第二個參數(shù)指定步長。函數(shù)會返回一個String.Index類型,這是一個字符串的字素位,我們可以使用這個字素位來插入或者刪除String中的元素,用法如圖2.18所示。圖2.18獲取字符串的String.Indexadvance會跳過整個字素而不是一個字符。如圖2.18所示,index為String.Index類型,和數(shù)組類型一樣,String類型支持下標操作。首先指定起始是從頭部開始,還是從尾部開始;頭部開始調(diào)用startIndex,尾部開始調(diào)用endIndex。然后調(diào)用advancedBy指定“步長”,“步長”使用整型格式。上例中指定了“步長”為3,通過startIndex和advancedBy組合生成了一個字符串頭部字素后面的第三個字素的下標(下標的具體用法會在后面講到),通過下標取值返回的是l,證明“à”作為一個完整的字素被跳過了。受Swift3.0中函數(shù)語法變動的影響,String中的API也發(fā)生了一些變化,Swift3.0中取下標的API統(tǒng)一使用index方法:

varstr="Heàllo"

str[str.index(str.startIndex,offsetBy:3)]

需要注意的是,下標取值并不能保證安全,如果下標超出了字符串末尾字符的下標,那么程序會掛掉。String提供了一個編譯期檢查下標是否越界的API,用法如下:

str[str.startIndex.advancedBy(6,limit:str.endIndex)]

Swift3.0中的版本為:

str[str.index(str.startIndex,offsetBy:6,limitedBy:str.endIndex)!]

一旦你指定的下標越界就會立即拋出錯誤。最后我們使用之前講到的范圍來截取str的子串,在截取起始終止位置的時候不能直接用Int類型,而是必須采用advance的辦法,做法如圖2.19所示,示例中最后截取的子串為“e3à”。圖2.19截取子串你可能會覺得這樣的用法非常麻煩,然而這也正是Swift語言進步的原因之一。同理,Swift3.0中需要使用下面的格式:

varstr="Heàllo"

letstart=str.index(str.startIndex,offsetBy:1)

letend=str.index(str.startIndex,offsetBy:3)

str[start...end]

OC中的NSString類型無非處理多個字符組成的字素,在Swift1.2版本中,弱化了String和NSString的關聯(lián),因此無法直接把一個NSString類型的值遞給一個String類型的變量;但是在Swift2.0之后,重新建立了NSString和String之間的橋接。由于String是比NSString更高級的對象,因此把NSString對象賦值給String對象時需要使用構(gòu)造器進行轉(zhuǎn)換,而String賦值給NSString對象時可以直接賦值,如圖2.20所示。圖2.20NSString與String的轉(zhuǎn)換不過在Swift3.0版本中,String與NSString之間的傳值需要遵循嚴格的類型轉(zhuǎn)化:

vars1:NSString="NSStr"

vars2:String=String(s1)

vars3:String="Str"

vars4:NSString=s3asNSString//

需要轉(zhuǎn)類型

字符串中還有很多有用的方法,比如rangeOfString會返回一個可選類型的范圍Range<String.Index>。我們可以使用這個方法獲得一個浮點數(shù)的整數(shù)部分,代碼如下:

letnum="123.45"

letdeRange=num.rangeOfString(".")//

該方法返回的是可選型

letwholeNumber=num[num.startIndex..<deRange!.startIndex]

playground中的結(jié)果如圖2.21所示。圖2.21使用rangeOfString獲得一個浮點數(shù)的整數(shù)部分Swift3.0中,rangeOfString遵照新的命名格式:

letnum="123.45"

letdeRange=num.range(of:".")//

該方法返回的是可選型

letwholeNumber=num[num.startIndex..<deRange!.lowerBound]

并且你可以看到String的Range不再提供startIndex這個參數(shù),取而代之的是新的命名lowerBound,與String的startIndex作出區(qū)分。此外還可以替換或者刪除字符串中的某部分,刪除子串可以使用removeRange方法:

varstr="Hello"

letstartIndex=str.startIndex.advancedBy(1)//

字母

e

letendIndex=str.startIndex.advancedBy(3)//

第二個字母

l

str.removeRange(startIndex...endIndex)結(jié)果如圖2.22所示。圖2.22removeRange方法的使用在Swift3.0中,removeRange的命名改為removeSubrange:

varstr="Hello"

letstart=str.index(str.startIndex,offsetBy:1)

letend=str.index(str.startIndex,offsetBy:3)

str.removeSubrange(start...end)

Swift中單個字素是Character類型的,刪除單個字素的方法是removeAtIndex。注意,無論是刪除整段還是單個字素,方法的參數(shù)類型都是String.Index。下面是刪除單個字素的示例:

varstr="Hello"

letstartIndex=advance(str.startIndex,1)

str.removeAtIndex(startIndex)

print(str)

playground中的運行結(jié)果如圖2.23所示。圖2.23removeAtIndex方法的使用Swift3.0版本:

varstr="Hello"

letstart=str.index(str.startIndex,offsetBy:1)

str.remove(at:start)

print(str)

替換子字符串的方法與刪除類似,有兩個參數(shù):替換的范圍和用來替換的內(nèi)容。示例如下:

varstr="Hello"

letstartIndex=str.startIndex.advancedBy(1)

letendIndex=str.startIndex.advancedBy(3)

在圖2.24中,str.replaceRange(startIndex...endIndex,with:"new")。以上代碼將“Hello”中的“ell”子串替換為“new”,playground中運行結(jié)果如圖2.24所示。圖2.24replaceRange方法的使用with參數(shù)的字符串位數(shù)不必與替換掉的子串位數(shù)相同,也就是說,你可以寫成str.replaceRange(startIndex...endIndex,with:"newwwwwwwww")這樣的格式。Swift3.0版本:

varstr="Hello"

letstart=str.index(str.startIndex,offsetBy:1)

letend=str.index(str.startIndex,offsetBy:3)

str.replaceSubrange(start...end,with:"new")

字符串中還有一些與數(shù)組交互的方法,后面在講到數(shù)組的時候會介紹這些方法,一起見證Swift語言的神奇。2.5集合類型Swift中有三種集合類型——數(shù)組、集合和字典,其中集合是Swift1.2版本加入的新成員。Swift中的數(shù)組用來順序存儲相同類型的數(shù)據(jù),數(shù)組成員可以重復。集合類型的概念類似于我們在數(shù)學中所學的集合;和數(shù)組一樣,Swift中的集合也是用來順序存儲相同類型的數(shù)據(jù),但是集合成員不能重復。字典類型雖然無序,但是要求存儲的成員必須是相同的類型,字典中的成員使用“鍵值對”格式。2.5.1數(shù)組OC中的數(shù)組分為NSArray和NSMutableArray兩種,分別表示不可變的數(shù)組和可變的數(shù)組,這兩種數(shù)組類型都可以存儲任何類型的實例。Swift中的數(shù)組使用Array關鍵字定義,或者使用類型推斷來初始化;Swift中的數(shù)組是類型安全的,數(shù)據(jù)值在被存入數(shù)組之前類型必須明確。通常定義一個數(shù)組使用var關鍵字,如果使用let關鍵字,則證明數(shù)組是一個常量,將不能使用方法來增加或者刪除這個數(shù)組中的元素。如果數(shù)組中只有四個元素,而你要訪問第五個元素,那么會拋出運行時錯誤,提示數(shù)組越界。創(chuàng)建一個數(shù)組的實例有兩種方式,第一種方式如下:

vara=Array<String>()//

得到一個字符串類型的空數(shù)組

這是一種泛型結(jié)構(gòu)體式的初始化方法。簡單講一下泛型的相關知識,一個數(shù)組中的值必須是相同類型的,但我們的數(shù)組可以選擇全部存儲整數(shù),也可以選擇全部存儲浮點數(shù)。比如上面的代碼中創(chuàng)建了一個存儲字符串的數(shù)組實例。由于這種類型的不確定性,所以將數(shù)組定義為Array<T>,如果給T賦不同類型的值,那么創(chuàng)建的就是不同值類型的數(shù)組。第二種方式如下,和第一種方式是等價的:

vara=[String]()

這種形式更加簡潔,也是官方推薦的寫法,在日常開發(fā)中建議使用這種寫法。而在OC中,因為Array是引用類型(有關值類型和引用類型的知識,會在后面講到),為了避免“共享”問題的出現(xiàn),創(chuàng)建一個可變數(shù)組的代碼要復雜一些:

NSArray*exampleOfNSArray=@[@"

糖醋里脊

",@"

宮保雞丁

",@"

水煮魚

",@"

魚香肉絲

",@"

大盤雞

"];

NSMutableArray*exampleOfNSMutableArray=[[NSMutableArrayalloc]

initWithArray:exampleOfNSArraycopyItems:YES];

在Swift中建立一個數(shù)組的代碼如下,這一次我們使用了類型推斷:

varexampleOfArray=["

糖醋里脊

","

宮保雞丁

","

水煮魚

","

魚香肉絲

","

大盤雞

"]

和NSArray相似,Swift中的Array也有很多有用的屬性,比如只讀屬性count返回數(shù)組中的元素個數(shù),效果如圖2.25所示。圖2.25查看數(shù)組的count屬性在OC中,可以使用NSMutableArray中的方法addObject來增加數(shù)組中的元素;而Swift中的方法更簡單,可以使用“+=”,比如給之前的數(shù)組增加一個元素:

exampleOfArray+=["AD

鈣奶

"]

注意,這個方法是數(shù)組間的,也就是說,只要數(shù)組類型相同,就可以把一個數(shù)組中的元素加入到另一個數(shù)組中。如果只是一個單個元素要加入數(shù)組中,則需要在元素外面加上[],新元素會加在數(shù)組的尾部,效果如圖2.26所示。圖2.26使用“+=”向數(shù)組中加入新元素當然也可以使用其他方法向數(shù)組中添加元素,比如使用append方法可以達到和“+=”相同的目的。下面向數(shù)組尾部增加一個元素:

exampleOfArray.append("AD

鈣奶

")

要取出或者替換數(shù)組中的元素,需要使用下標索引,這一點與OC相同。數(shù)組中的索引從0開始,代碼如下所示:

vararrayItem=exampleOfArray[0]

exampleOfArray[1]="

宮保山藥

"

可以使用范圍來獲取或者替換數(shù)組中的多個元素,替換的元素和原有的元素個數(shù)可以不同:

exampleOfArray[1...2]=["AD

鈣奶

"]

上面的代碼中使用一個元素替換了原數(shù)組中的兩個元素,替換之后數(shù)組的長度也發(fā)生了變化,效果如圖2.27所示。圖2.27替換數(shù)組中的多個元素在數(shù)組的下標中,使用范圍返回的結(jié)果是該數(shù)組的一個“片段”,該片段不會占用額外的存儲空間,而只是代表了原數(shù)組的某個數(shù)據(jù)段。如果想把新元素插入到指定位置,則可以使用方法insert:

exampleOfArray.insert("AD

鈣奶

",atIndex:3)

效果如圖2.28所示。圖2.28使用insert方法向數(shù)組指定位置插入元素參數(shù)atIndex指定新元素在數(shù)組中的位置。注意,索引是從0開始的,因此圖2.28中的代碼是指在數(shù)組的第四個位置插入新元素“AD鈣奶”;被插入位置上原來的元素及之后的元素會向后移動,數(shù)組的長度會增加1。Swift3.0版本的插入方法使用了更簡潔的參數(shù)命名:

exampleOfArray.insert("AD

鈣奶

",at:3)

可以使用removeLast方法刪除數(shù)組的最后一個元素:

exampleOfArray.removeLast()

也可以使用removeAtIndex方法刪除指定位置的元素:

exampleOfArray.removeLast()

Swift3.0版本:

exampleOfArray.remove(at:0)

分別使用上面兩個方法刪除了數(shù)組的最后一個和第一個元素,效果如圖2.29所示。圖2.29刪除不同位置的元素需要注意的是,與字典中“搜索”性質(zhì)的方法不同,數(shù)組中的許多方法是基于下標的,也就是說,這些方法不會返回可選型的值。比如上面提到的removeLast方法,如果對一個空數(shù)組調(diào)用removeLast方法會導致“越界”。為了避免這樣的情況,在使用這些方法時最好首先判斷邊界條件,比如:

if!b.isEmpty{

b.removeLast()

}

2.5.2集合集合和數(shù)組非常相似,區(qū)別是集合中不會有重復的元素,并且集合中的成員是無序的。有些情況下我們需要數(shù)組中的值不包含相同的元素,這個時候就需要使用集合。我們可以把一個數(shù)組轉(zhuǎn)換成集合,方法如下:

varexampleOfArray=["

糖醋里脊

","

宮保雞丁

","

水煮魚

","

魚香肉絲

","

大盤雞

","

大盤雞

"]

varexampleOfSet=Set(exampleOfArray)

或者把變量聲明為集合??梢允褂靡粋€數(shù)組樣式的字面量來初始化集合,這樣在給這個變量賦值的時候,即便數(shù)組中存在重復的元素,變量中也不會出現(xiàn)重復元素,例如:

varexampleOfSet:Set=["

糖醋里脊

","

宮保雞丁

","

水煮魚

","

魚香肉絲"

,"

大盤雞

","

大盤雞

"]

效果如圖2.30所示,集合中的元素是用大括號括起來的(和字典一樣,Swift中大括號表示一種無序),這和我們在數(shù)學上學到的集合的表示方法相同。因為大括號和閉包的格式?jīng)_突了,所以無法用大括號括起元素的方法作為字面量來初始化一個集合,所以必須借助數(shù)組的格式,并且需要將變量顯式地聲明為集合。數(shù)組和集合都可以使用中括號格式的字面量做初始化,其實是因為二者都遵守了ArrayLiteralConvertible協(xié)議,這個協(xié)議的相關知識會在第3章中介紹。圖2.30聲明一個集合集合也有許多方法,我們需要了解的是添加和刪除元素的方法,這些方法都有返回值。

exampleOfSet.insert("AD鈣奶")//

新增一個元素

exampleOfSet.remove("AD鈣奶")//

刪除一個元素

由于集合中不存在重復的元素,并且集合是無序的,因此在刪除元素時不需要指定下標,只需指定元素的名稱即可。如果集合中沒有該元素,則remove方法會返回nil。集合的最廣泛應用是求多個集合的交集、差集、并集和補集,這些都是數(shù)學上的概念,本書不做詳細介紹,圖2.31給出了兩個集合的運算示例。圖2.31兩個集合的運算示例2.5.3字典字典有點類似于數(shù)組,它的鮮明特征是鍵值對[Key,Value]。和數(shù)組一樣,字典的創(chuàng)建也有兩種方式:

varexampleOfDictionary=Dictionary<String,Int>()

等同于:

varexampleOfDictionary=[String:Int]()

很明顯字典的定義也是泛型的,值的部分是完全的泛型,鍵的部分雖然是泛型的,但是要求該泛型必須遵守Hashable協(xié)議。對泛型的作用范圍進行約束,也是協(xié)議的職責之一。本書的核心是面向協(xié)議編程,會在后面的章節(jié)重點介紹協(xié)議的用法,這里只做了解。我們可以使用鍵來索引任意類型的值,但是和數(shù)組一樣,一個字典中的值必須是同一種類型。我們使用鍵來訪問值,如果鍵不在字典中,那么就會返回一個nil。這點很好理解,就如字面意思那樣,我們遇到不認識的字時會去查字典,結(jié)果可能查到也可能沒查到,本質(zhì)是一個“搜索”過程。我們可以使用類型推斷來新建一個字典:

varexampleOfDictionary=["

年齡

":25,"

身高

":175]

同樣的字典在OC中的創(chuàng)建方式如下:

NSDictionary*exampleOfDictionary=@{@"

年齡

":@25,@"

身高

":@175};

這里使用了字面量的方式來創(chuàng)建一個NSDictionary,由于NSDictionary中只能使用OC中的對象,所以數(shù)字要轉(zhuǎn)換成NSNumber。使用字面量的方式只需在數(shù)字前面加上“@”即可。和數(shù)組一樣,我們可以使用只讀屬性count來獲取字典中鍵值對的數(shù)量,如圖2.32所示。圖2.32字典中的count屬性如果想要獲取或者修改字典中的值,則可以使用鍵來索引,形式如下:

exampleOfDictionary["

年齡

"]=20

添加一個新鍵值對的形式和上面的代碼類似,如果賦值語句中字典的鍵值之前沒有存儲在字典當中,則會將這個鍵值對自動添加到字典中,如圖2.33所示。圖2.33修改和添加鍵值對使用字典的updateValue方法可以達到同樣的目的,不過這個方法會返回修改前的值;如果修改的鍵之前不存在于字典中,則會新增這個鍵值對,同時返回nil,如圖2.34所示。圖2.34使用updateValue方法獲取舊值可以使用下標的方法來移除字典中的鍵值對,只需給某個鍵對應的值賦值為nil即可,如圖2.35所示。圖2.35使用下標方法刪除鍵值對同樣,使用removeValueForKey方法(Swift3.0中為removeValue(forKey:))可以達到同樣的目的,與updateValue一樣,removeValueForKey方法會返回被刪除的值,如圖2.36所示。圖2.36使用removeValueForKey方法刪除鍵值對2.6控制流Swift中的控制流非常強大,既可以使用for和while語句進行多次循環(huán),也可以使用if、guard和switch進行判斷后執(zhí)行分支代碼。與控制流相關的一個重要知識點是模式匹配,本書會在第3章中專門講解。2.6.1for循環(huán)在Swift中,最常使用的for循環(huán)是for

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論