版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
Swift面向協(xié)議編程注:因內(nèi)容過長上傳受限制,本文檔只顯示部分內(nèi)容,完整版文檔請(qǐng)下載此文檔后留言謝謝。目錄\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基礎(chǔ)語法\h2.1基礎(chǔ)知識(shí)\h2.1.1命名規(guī)則\h2.1.2常量與變量\h2.1.3類型推測(cè)\h2.1.4注釋\h2.1.5輸出常量和變量\h2.2基本數(shù)據(jù)類型\h2.2.1整數(shù)\h2.2.2浮點(diǎn)數(shù)\h2.2.3布爾類型\h2.2.4元組類型\h2.2.5可選型\h2.3基本運(yùn)算符\h2.3.1賦值運(yùn)算符\h2.3.2數(shù)值運(yùn)算\h2.3.3自增和自減運(yùn)算\h2.3.4復(fù)合賦值\h2.3.5比較運(yùn)算\h2.3.6三元運(yùn)算符\h2.3.7邏輯運(yùn)算符\h2.3.8范圍\h2.3.9括號(hào)優(yōu)先級(jí)\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開關(guān)語句\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存儲(chǔ)屬性\h2.10.2計(jì)算屬性\h2.10.3屬性觀察器\h2.10.4類型屬性\h2.11方法\h2.12下標(biāo)\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擴(kuò)展\h2.17.1擴(kuò)展計(jì)算屬性\h2.17.2擴(kuò)展構(gòu)造器\h2.17.3擴(kuò)展方法\h2.17.4擴(kuò)展下標(biāo)\h2.18協(xié)議\h2.18.1聲明協(xié)議\h2.18.2遵守協(xié)議\h2.18.3實(shí)現(xiàn)協(xié)議\h2.18.4實(shí)現(xiàn)擴(kuò)展\h2.18.5協(xié)議擴(kuò)展補(bǔ)充\h2.18.6協(xié)議的繼承\(zhòng)h2.19泛型\h2.19.1節(jié)點(diǎn)泛型\h2.19.2泛型協(xié)議\h2.19.3泛型對(duì)象\h2.19.4泛型方法\h2.19.5協(xié)議中的where關(guān)鍵字\h2.19.6泛型特化\h2.20Swift語法補(bǔ)充\h2.20.1斷言\h2.20.2precondition\h第3章Swift進(jìn)階語法\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中的錯(cuò)誤處理\h3.1.8隱式解包\h3.1.9關(guān)于可選型的思考\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的對(duì)比\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帶下標(biāo)的數(shù)組遍歷\h3.3.14Demo演示\h3.4Objective-C兼容性\h3.4.1類型橋接\h3.4.2OC和Swift的設(shè)計(jì)區(qū)別\h3.5Swift內(nèi)存管理\h3.5.1棧和堆\h3.5.2值類型和引用類型\h3.5.3Copy-on-Write\h3.5.4利用引用類型的“共享”\h3.5.5ARC(自動(dòng)引用計(jì)數(shù))\h3.5.6循環(huán)引用\h3.5.7弱引用與無主引用\h3.5.8柯里化與方法參數(shù)中的閉包\h3.5.9@noescape與@autoclosure\h3.5.10靜態(tài)派發(fā)和動(dòng)態(tài)派發(fā)\h3.5.11協(xié)議類型的存儲(chǔ)屬性\h3.5.12靜態(tài)多態(tài)與動(dòng)態(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關(guān)鍵字\h第4章iOS開發(fā)入門\h4.1iOS系統(tǒng)初探\h4.1.1核心OS(CoreOS)層\h4.1.2核心服務(wù)(CoreServices)層\h4.1.3媒體(Media)層\h4.1.4CocoaTouch層\h4.2MVC模式\h4.2.1MVC簡介\h4.2.2iOS中的MVC\h4.3新建一個(gè)Swift工程\h4.4認(rèn)識(shí)InterfaceBuilder\h4.5構(gòu)建計(jì)算器界面\h4.5.1使用對(duì)象庫中的對(duì)象\h4.5.2使用檢查器設(shè)置對(duì)象\h4.5.3嘗試運(yùn)行程序\h4.5.4添加約束\h4.5.5關(guān)聯(lián)代碼\h4.5.6完善按鍵\h4.6實(shí)現(xiàn)計(jì)算器邏輯\h4.6.1補(bǔ)全鍵盤\h4.6.2給鍵盤添加約束\h4.6.3實(shí)現(xiàn)數(shù)字顯示功能\h4.6.4實(shí)現(xiàn)運(yùn)算邏輯\h4.7修改計(jì)算器為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中心與對(duì)齊\h4.9.3尺寸與比例\h4.9.4絕對(duì)位置與擠壓\h第5章面向協(xié)議編程\h5.1繼承與組合\h5.2搭建頁面\h5.3創(chuàng)建storyboard對(duì)應(yīng)的子類\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)境正所謂“工欲善其事,必先利其器”,在開始學(xué)習(xí)Swift之前,我們需要做好相關(guān)的準(zhǔn)備。由于Swift是蘋果公司的“親兒子”,所以你可以在Mac上快速開啟你的Swift之旅,本書使用的開發(fā)工具是蘋果的Xcode。1.1Swift介紹1.1.1Swift的前世今生在閱讀本書之前,可能你已經(jīng)從其他渠道了解了一些Swift的相關(guān)信息,下面簡單介紹一下Swift語言的前世今生。作為編程語言界的“小鮮肉”,Swift是蘋果公司在2014年WWDC(蘋果全球開發(fā)者大會(huì))上發(fā)布的全新的編程語言。Swift是供iOS和OSX應(yīng)用編程的新編程語言,基于C和Objective-C,沒有C的一些兼容約束。Swift采用了安全的編程模式,并添加新的功能,以使得編程更加簡單、靈活、有趣。界面則基于深受廣大碼民喜愛的Cocoa和CocoaTouch框架,展示了軟件開發(fā)的新方向。有人笑言Swift語言是語言進(jìn)化鏈頂端的語言,因?yàn)樗诤狭撕芏喱F(xiàn)代編程語言的優(yōu)點(diǎn),加入了諸如閉包這樣的高級(jí)語言特性。在語法結(jié)構(gòu)上,Swift有點(diǎn)類似于JavaScript這樣的腳本語言,但更加簡潔優(yōu)雅。2010年7月,LLVM編譯器的原作者,暨蘋果開發(fā)者工具部門總監(jiān)克里斯·拉特納(ChrisLattner)開始著手Swift編程語言的工作,還有一個(gè)Dogfooding團(tuán)隊(duì)大力參與其中。至2014年6月發(fā)表時(shí),Swift歷經(jīng)了大約4年的開發(fā)期。克里斯在開發(fā)Swift之前的一項(xiàng)偉大成就是為蘋果公司開發(fā)了LLVM編譯框架。由于他在編譯框架方面的豐富經(jīng)驗(yàn),使得Swift不但語法簡潔,而且對(duì)編譯期的速度也有所優(yōu)化,讀者在使用Swift進(jìn)行開發(fā)時(shí)一定深有感觸。開源之后,Swift得到了更多開發(fā)者的青睞,在最近幾個(gè)月的Tiobe世界編程語言排行榜上,Swift都反超了Objective-C,排名穩(wěn)中有升,2016年8月的Tiobe世界編程語言排行榜如圖1.1所示。圖1.12016年8月的Tiobe世界編程語言排行榜1.1.2Swift與Objective-C我們知道,以前進(jìn)行iOS開發(fā)時(shí)使用的是Objective-C(以下簡稱OC)這門古老的語言,Swift語言的發(fā)布對(duì)于熟悉OC開發(fā)的程序員來說是一件令人興奮的事情。因?yàn)镺C是C語言的超集,比較像C++這樣的傳統(tǒng)面向?qū)ο笳Z言,而沒有很多現(xiàn)代高級(jí)語言的特性。并且由于OC是一門消息傳遞語言,而不是傳統(tǒng)的函數(shù)調(diào)用語言,因此OC里面中的括號(hào)語法使得很多從其他編程語言轉(zhuǎn)投OC開發(fā)的程序員很不適應(yīng)。但是這并不代表OC不好。任何一門新興的語言都在不斷變化之中,由于Swift的發(fā)布時(shí)間較短,而筆者學(xué)習(xí)Swift語言的時(shí)候還處在Swift語言的元年,筆者的學(xué)習(xí)過程跨越了Swift1.1版本到Swift3版本,語法有很多變動(dòng)。如果你正在維護(hù)一個(gè)大型項(xiàng)目,那么語法的變動(dòng)肯定是你不想看到的。所幸蘋果承諾3.0版本將是Swift最后一個(gè)“破壞性”升級(jí)的版本。對(duì)于有志于從事iOS開發(fā)工作或者是服務(wù)端開發(fā)的讀者,使用Swift可能是一件“當(dāng)下痛苦,未來愉悅”的事情。本書在介紹Swift語法時(shí)也會(huì)穿插OC中的一些代碼做對(duì)比,讓讀者更加了解兩種語言的差異。最后,筆者建議在學(xué)習(xí)Swift語言的同時(shí),應(yīng)熟悉OC語言,兩件兵器同時(shí)在手,笑傲職場,豈不更加游刃有余!1.2MacOSX操作系統(tǒng)OSX是蘋果公司為Mac系列產(chǎn)品開發(fā)的專屬操作系統(tǒng)(新版本已經(jīng)正式更名為MacOS了),基于UNIX系統(tǒng),有一定Linux基礎(chǔ)的人使用OSX時(shí)會(huì)更加得心應(yīng)手。OSX操作系統(tǒng)的獲取方式有兩種,最簡單的一種是買一臺(tái)蘋果電腦,無論是哪個(gè)系列,這些電腦都預(yù)裝了OSX操作系統(tǒng)。如果你不打算購買蘋果電腦,另外一種方式是在Windows環(huán)境下用虛擬機(jī)安裝OSX操作系統(tǒng),也就是我們通常所說的“黑蘋果”,網(wǎng)上有詳細(xì)的教程,筆者在此不做過多的介紹。但需要強(qiáng)調(diào)的是,“黑蘋果”下的開發(fā)有著各種各樣的問題,會(huì)拖累我們的學(xué)習(xí)進(jìn)度,如果你只是想嘗嘗鮮,了解一下Swift語言,那么你大可不必購買一臺(tái)真正的蘋果電腦。但是對(duì)于一個(gè)有志于在現(xiàn)在或者將來進(jìn)行iOS系統(tǒng)開發(fā)的讀者來說,一臺(tái)真正的蘋果電腦是必不可少的;因?yàn)椴粌H企業(yè)中的iOS開發(fā)全部是在蘋果電腦上進(jìn)行的,甚至一些其他領(lǐng)域的開發(fā)也會(huì)選擇蘋果電腦,而蘋果電腦的易用性和良好的操控性可以大大提升你的編程舒適度。1.3Xcode簡介和獲取方法1.3.1Xcode簡介Xcode是蘋果推出的編程工具,必須安裝在MacOSX系統(tǒng)上,Xcode7.3.1要求OSX的版本不低于10.11。Xcode7的啟動(dòng)界面如圖1.2所示,本書所展示的示例代碼全部使用正式版本的Xcode進(jìn)行編寫。2015年9月,Xcode7正式版發(fā)布,Swift語言進(jìn)入2.X時(shí)代,Xcode7.3.1中使用的Swift語言版本是2.2版本。圖1.2Xcode7啟動(dòng)界面從圖1.2可以看到,啟動(dòng)Xcode后,左側(cè)可以選擇新建一個(gè)playground文件、一個(gè)Xcode工程或者檢查一個(gè)已經(jīng)存在的項(xiàng)目,右側(cè)可以顯示使用Xcode打開的工程或者文件的歷史記錄。本書前幾章主要介紹Swift的語法,筆者推薦大家使用playground進(jìn)行Swift語言的學(xué)習(xí)。1.3.2playground簡介playground是隨著Swift在蘋果的2014WWDC上發(fā)布的,只有在Xcode6之后的版本中才能看到它的身影。Xcode的playground功能是Swift為蘋果開發(fā)工具帶來的最大創(chuàng)新。該功能提供了強(qiáng)大的互動(dòng)效果,能讓Swift源代碼在撰寫過程中實(shí)時(shí)顯示其運(yùn)行結(jié)果,避免了編譯運(yùn)行的耗時(shí),大大提高了學(xué)習(xí)效率。我們只需在Xcode啟動(dòng)界面的左側(cè)單擊第一個(gè)條目就可以創(chuàng)建一個(gè)playground,如圖1.3所示。圖1.3創(chuàng)建一個(gè)Playground之后給新建的文件取名并選擇保存路徑,playground的界面就展示在我們面前了。如圖1.4所示。新的playground中會(huì)有一些默認(rèn)的代碼,可以看到界面分為左右兩部分,左側(cè)是代碼,右側(cè)是代碼結(jié)果的實(shí)時(shí)展示,簡單易用。
注意:代碼第三行“importUIKit”中的import關(guān)鍵字的作用是向Swift中導(dǎo)入框架,UIKit框架包含了頁面開發(fā)中的各種組件,我們會(huì)在后面的章節(jié)詳細(xì)介紹UIKit中各個(gè)組件的用法。圖1.4playground界面展示1.3.3Xcode的獲取方法用戶可以通過蘋果的官方商店下載Xcode,商店中的Xcode是正式版本,筆者推薦大家使用穩(wěn)定版本,而不要使用測(cè)試版本。需要注意的是,在蘋果商店中下載軟件時(shí)需要有APPID,如果沒有,可以免費(fèi)注冊(cè)一個(gè)。如圖1.5所示,打開蘋果商店,在右上角的搜索框中輸入“Xcode”,就可以找到Xcode并安裝它了。圖1.5在蘋果商店中搜索Xcode如果想要嘗試測(cè)試版本的Xcode,則通過蘋果的開發(fā)者網(wǎng)站就可以找到,只不過下載時(shí)需要蘋果的開發(fā)者賬號(hào)。當(dāng)然,每次公布測(cè)試版本的Xcode之后,網(wǎng)上都有很多人共享,即便你沒有開發(fā)者賬號(hào)也可以從他們提供的網(wǎng)盤鏈接中下載。1.4iPhoneSDK簡介iPhoneSDK是蘋果公司提供的iPhone開發(fā)工具包,包括界面開發(fā)工具、集成開發(fā)工具、框架工具、編譯器、分析工具、開發(fā)樣本和一個(gè)模擬器。在早些年的iOS開發(fā)中,我們需要手動(dòng)安裝iPhoneSDK,現(xiàn)在Xcode中已經(jīng)集成了iPhoneSDK,我們無須自己再去配置它。隨著Xcode版本的升級(jí),其集成的iPhoneSDK版本也會(huì)升級(jí),比如Xcode7.3版本的iPhoneSDK版本號(hào)是9.3。需要注意的是,在真機(jī)測(cè)試時(shí),Xcode中需要包含真機(jī)上的系統(tǒng)版本所對(duì)應(yīng)的iPhoneSDK。第2章
Swift基礎(chǔ)語法相信通過第1章的介紹,你已經(jīng)迫不及待地想要在Swift的舞臺(tái)上大展身手了。在本章,你將正式接觸到Swift的語法。本書盡可能詳盡地從用法與原理上解讀Swift的語法,遇到不易理解的地方希望讀者可以細(xì)細(xì)揣摩,夯實(shí)語法基礎(chǔ)。為了突出Swift與Objective-C的區(qū)別,在介紹Swift語法時(shí),會(huì)展示一些簡單的OC語法作為對(duì)比;即便之前沒有接觸過OC語法,只要你有一定的編程基礎(chǔ),就能輕松看懂。本章絕大多數(shù)代碼都在playground中進(jìn)行演示。2.1基礎(chǔ)知識(shí)2.1.1命名規(guī)則在Swift中,我們所定義的變量、常量、類或者方法都需要有各自的名稱,名稱是區(qū)分它們的唯一標(biāo)識(shí)。如果你使用相同的名稱重復(fù)定義,那么就會(huì)收到系統(tǒng)的報(bào)錯(cuò)提示。這里所說的名稱在計(jì)算機(jī)語言中的標(biāo)準(zhǔn)稱呼是標(biāo)識(shí)符。標(biāo)識(shí)符的構(gòu)成有一定的規(guī)范:標(biāo)識(shí)符中大小寫代表不同的含義,所以XIAOMING和xiaoming代表兩個(gè)不同的標(biāo)識(shí)符。不能包含數(shù)學(xué)符號(hào)、箭頭、保留的Unicode碼位、連線符與制表符。可以包含數(shù)字,但是數(shù)字不能作為標(biāo)識(shí)符的首字符。不能使用Swift保留的關(guān)鍵字作為標(biāo)識(shí)符(雖然Proposal0071中表示關(guān)鍵字已經(jīng)可以被用作標(biāo)識(shí)符了,但是Swift3.0正式版中仍舊無法使用)。值得注意的是,Swift的標(biāo)識(shí)符可以使用中文命名,或許你已經(jīng)習(xí)慣了用abc來命名變量,使用i和j來保存循環(huán)的次數(shù),但現(xiàn)在你可以使用諸如“重量”、“數(shù)量”這樣的中文來作為標(biāo)識(shí)符。這得益于Swift中的字母采用的是Unicode編碼,Unicode的中文翻譯是統(tǒng)一編碼制,其中不僅有英文,還有亞洲文字,甚至我們常用的表情“”也在Unicode編碼之中,所以如果你夠任性,甚至可以使用一個(gè)笑臉來作為變量名。Swift中類、協(xié)議、結(jié)構(gòu)體、枚舉的標(biāo)識(shí)符中的第一個(gè)字符通常要大寫,而方法的標(biāo)識(shí)符中第一個(gè)字母通常為小寫,以示區(qū)分。另外,標(biāo)識(shí)符整體的命名采用“駝峰式”的命名規(guī)則,即如果標(biāo)識(shí)符由多個(gè)單詞組成,那么標(biāo)識(shí)符的首字母遵從上面的命名規(guī)則,而其他單詞的首字母全部大寫,比如maxNumberOfArray,整個(gè)標(biāo)識(shí)符中的多個(gè)單詞通過大寫的首字母做出了清晰地劃分,看起來就像是駱駝的駝峰一樣,避免了使用下畫線“_”來分隔單詞。良好的命名習(xí)慣,可以極大地提升代碼的可讀性,僅通過標(biāo)識(shí)符的名稱就可以清晰地表達(dá)出代碼的含義。2.1.2常量與變量在OC中,常量與變量的劃分有時(shí)與具體的類型綁定。比如,變量字符串使用NSMutableString定義,常量字符串使用NSString定義。再如,可變數(shù)組使用NSMutableArray定義,而不可變數(shù)組使用NSArray定義。Swift語言消除了這種命名上的冗余性,常量和變量定義變得非常簡單。如果要定義一個(gè)常量,則使用let關(guān)鍵字定義;如果要定義一個(gè)變量,則使用var關(guān)鍵字定義。無論你想定義的是整型、浮點(diǎn)型、數(shù)組還是字符串,都只需使用這兩個(gè)關(guān)鍵字來進(jìn)行區(qū)分。例如下面的代碼:
letname="
教科書的靈魂小明同學(xué)
"http://
使用
let
關(guān)鍵字定義了一個(gè)常量
name
varhisAge=8//
使用
var
關(guān)鍵字定義了一個(gè)變量
hisAge
上面的語句可以理解成兩步,首先通過let和var定義了一個(gè)常量和變量,然后使用“=”初始化這個(gè)常量和變量。變量的值可以在后面的代碼中通過賦值語句進(jìn)行修改,而常量的值一旦設(shè)定將不能更改。
name="
了不起的李雷
"http://
程序會(huì)報(bào)錯(cuò),提示你不能修改常量
hisAge=15//
年齡是個(gè)變量,所以修改年齡沒有問題
Swift的開發(fā)原則是盡量使用常量,因?yàn)槌A康倪\(yùn)行效率更高。如果你定義的變量在代碼中沒有發(fā)生改變,那么編譯器會(huì)提示你把變量修改成常量??赐晟厦娴拇a,你可能注意到了,每一行代碼的末尾都沒有使用“;”。這并不是筆者粗心大意漏掉了。在初學(xué)C語言的時(shí)候,你可能因?yàn)槁┑袅恕?;”而吃了不少苦,但在Swift中,我們可以徹底和分號(hào)說拜拜了。在一行完整的語句結(jié)束后,我們只需換行即可;當(dāng)然,在代碼的末尾寫上“;”也完全沒有問題。比如,下面的兩種寫法是等價(jià)的,只不過在實(shí)際編程中,通過換行的方式來分隔代碼效率會(huì)更高。
varcar="
奧迪
"
varcar="
奧迪
";
2.1.3類型推測(cè)在之前的代碼中,除“分號(hào)”的使用外,另外一個(gè)令人疑惑的地方是,我們?cè)诙x一個(gè)常量或者變量的時(shí)候,并沒有指定它的類型,這樣的寫法在playground中卻沒有報(bào)錯(cuò),這似乎有些不合常理。因?yàn)樵贠C中聲明一個(gè)變量時(shí),必須要指定它的數(shù)據(jù)類型,例如:
constintcount=10;
doubleprice=9.9;
NSString*message=@"ThisisObjective-C";
你可能會(huì)覺得Swift不是一門強(qiáng)類型語言,然而事實(shí)恰恰相反,Swift是一門不折不扣的強(qiáng)類型語言。在聲明變量時(shí),不需要指定數(shù)據(jù)類型的特性依托于Swift強(qiáng)大的類型推測(cè)功能。在Swift中,聲明的常量和變量可以通過在初始化時(shí)判斷傳遞給它的具體值的類型,并把這個(gè)類型作為常量和變量的類型,如以下代碼所示:
letcount=10
//count
會(huì)被識(shí)別為
Int
varprice=9.9
//price
會(huì)被識(shí)別為
Double
varmessage="ThisisSwift"
//message
會(huì)被識(shí)別為
String
當(dāng)然,你也可以在聲明時(shí)顯式地指定常量和變量的數(shù)值類型:
varname:String="
小明
"http://
在聲明時(shí)指定
name
的數(shù)據(jù)類型
Swift是一門類型安全的語言,無論你是顯式地聲明類型,還是更習(xí)慣讓系統(tǒng)去做類型推測(cè),每個(gè)常量和變量的類型都是明確的;Swift會(huì)在編譯期檢查所有的類型,以保證系統(tǒng)在運(yùn)行期安全無誤,你永遠(yuǎn)不能給一個(gè)Int類型的常量或變量傳入一個(gè)String類型的值。2.1.4注釋有編程經(jīng)驗(yàn)的讀者對(duì)注釋肯定不會(huì)陌生,注釋一方面可以幫助我們更好地解釋代碼,另一方面還可以通過注釋具體的代碼段起到調(diào)試程序的作用。Swift中的注釋和其他語言中的注釋功能基本一致。注釋分為單行注釋和塊注釋。單行注釋在上面的代碼中已經(jīng)使用了很多次,在單行代碼的末尾使用//作為注釋的起點(diǎn),后面的文字均為注釋,注釋不會(huì)對(duì)代碼的執(zhí)行產(chǎn)生任何影響。如果需要注釋的內(nèi)容比較多,那么需要使用塊注釋,塊注釋使用/*作為起點(diǎn),使用*/作為終點(diǎn),起點(diǎn)與終點(diǎn)之間的內(nèi)容全部為注釋,不參與代碼的執(zhí)行,如下所示:
//
單行注釋格式
/*
塊注釋格式
*/
在Xcode中,選中需要注釋的內(nèi)容按下command+/鍵,可以快速注釋所選內(nèi)容;如果要取消注釋,則選中注釋的內(nèi)容,再次按下command+/鍵就可以取消注釋。在Xcode8中,需要在終端輸入sudo/usr/libexec/xpccachectl,然后重啟電腦才可以使用這個(gè)快捷鍵。2.1.5輸出常量和變量如果要把常量和變量的值輸出到中控臺(tái),則應(yīng)使用print函數(shù),這個(gè)函數(shù)是默認(rèn)換行的,比如:
print("
"我愛
Swift!")//
如果是在
Xcode
的工程中
,“
我愛
Swift”
會(huì)顯示在中控臺(tái)
print(items:Any...)是默認(rèn)換行的,參數(shù)items是可變參數(shù)。如果傳入多個(gè)參數(shù),則每個(gè)參數(shù)之間都會(huì)用一個(gè)空格隔開,比如下面的示例代碼:
print("1","2")
print("3","4")
打印結(jié)果是:1234你可以對(duì)items中的參數(shù)指定分隔符和終止符,即使用另一個(gè)重載的print方法:
print("a","b","c",separator:"*",terminator:"end")
打印結(jié)果是:a*b*cend
注意:帶有分隔符和終止符的print方法是不換行的,如果在上面的語句后面再加上一個(gè)普通的print:
print("a","b","c",separator:"*",terminator:"end")
print("111")
打印結(jié)果是:a*b*cend111Swift采用字符串插值的方式在輸出的內(nèi)容中加入常量或變量的值。首先將常量或變量名放入\()的括號(hào)中,然后將\(常量名)或者\(yùn)(變量名)當(dāng)作占位符插到字符串的相應(yīng)位置,這樣print函數(shù)在輸出時(shí)就會(huì)在該位置插入常量或變量的值,代碼如下:
letname="
小明
"
print("
我同桌名叫
\(name)")
playground中的實(shí)際效果如圖2.1所示。圖2.1字符串插值這樣的輸出方式相比OC中使用的NSLog函數(shù)更加直觀,同樣的功能在OC中的寫法如下:
NSString*name=@"
小明
";
NSLog(@"
我同桌名叫
%@",name);
注意:在筆者看來,print更適用于在playground中調(diào)試代碼。在真正的工程中,代碼通常比較復(fù)雜,如果你想知道某個(gè)對(duì)象的值,則加入一個(gè)print語句之后需要重新編譯,會(huì)消耗很多時(shí)間成本。而且在程序運(yùn)行時(shí),編譯器不會(huì)過濾我們手寫的print,而這些print對(duì)用戶而言是沒有任何意義的,所以在工程中盡量不要寫print,養(yǎng)成打斷點(diǎn)的好習(xí)慣。2.2基本數(shù)據(jù)類型本節(jié)將介紹Swift中的幾大類基本數(shù)據(jù)類型,包括整數(shù)、浮點(diǎn)數(shù)、布爾型、可選型和元組,接著會(huì)展示數(shù)字類型之間的轉(zhuǎn)換。至于字符串、集合、結(jié)構(gòu)體、類等類型,由于內(nèi)容較多,因此將會(huì)放在后面單獨(dú)的章節(jié)中進(jìn)行講解。需要注意的是,Swift中的數(shù)據(jù)類型雖然名稱和C語言中的數(shù)據(jù)類型相似,但是Swift中數(shù)據(jù)類型的首字母都是大寫的。2.2.1整數(shù)整數(shù)的定義為沒有小數(shù)部分的數(shù)字,可以帶有正負(fù)號(hào)。Swift提供了Int和UInt兩種整數(shù)類型,分別表示有符號(hào)和無符號(hào)的整數(shù)類型。另外Int和UInt后面可以帶有數(shù)字8、16、32和64,以表示8、16、32、64位的整數(shù)。一般來講,我們并不需要指定整數(shù)的長度,使用UInt的情況也很少,在開發(fā)中使用Int類型即可。Int和UInt都是可以自適應(yīng)平臺(tái)的類型,所以不需要關(guān)心自己的系統(tǒng)是64位還是32位。另外,整數(shù)類型有屬性max和min,分別表示不同整數(shù)類型的最大值和最小值,在Swift中我們?cè)L問屬性采用“點(diǎn)方法”。為了加深理解,請(qǐng)看圖2.2。圖2.2Int8與UInt8類型2.2.2浮點(diǎn)數(shù)浮點(diǎn)數(shù)是指有小數(shù)部分的數(shù)字,比如我們熟悉的圓周率π。浮點(diǎn)數(shù)類型比整數(shù)類型表示的范圍要大。Swift提供了兩種浮點(diǎn)數(shù)類型:Float和Double。Float表示32位浮點(diǎn)數(shù),而Double表示64位浮點(diǎn)數(shù)。選擇哪種類型的浮點(diǎn)數(shù)取決于你對(duì)精度的要求。2.2.3布爾類型Swift提供了一個(gè)非真即假的邏輯類型——布爾類型(Bool)。布爾類型有兩個(gè)布爾常量:true和false。我們可以使用類型推斷,給變量或者常量直接賦值為true或者false,這樣常量或者變量的類型就會(huì)被識(shí)別為布爾類型。布爾類型在編程中有非常重要的作用。需要注意的是,Swift中的布爾類型不同于OC中的BOOL類型,不再接受0代表false、1代表true的用法,如圖2.3所示。圖2.3Swift中“1”不能代表true2.2.4元組類型元組是Swift中一個(gè)非常好用的數(shù)據(jù)類型,它可以把多個(gè)值成員復(fù)合成一個(gè)值,并且這些成員的數(shù)據(jù)類型可以不同;把成員值放到一個(gè)括號(hào)中,以逗號(hào)分隔。我們可以使用元組來定義一些固定形式的信息,比如一個(gè)學(xué)生的身份信息:
letmessage=("
小明
",9,"
三年二班
")
這個(gè)元組類型就可以表達(dá)出一個(gè)三年級(jí)二班名叫小明的9歲同學(xué),結(jié)構(gòu)非常精簡。上面的代碼在playground中的顯示如圖2.4所示。圖2.4一個(gè)包含三個(gè)成員值的元組在右側(cè)的輸出頁面上我們可以看到,元組中每個(gè)成員值的前面都顯示了一個(gè)默認(rèn)的索引,我們可以通過索引直接獲得元組中各部分的值,如圖2.5所示。圖2.5使用索引獲取元組成員的值我們也可以給每個(gè)成員變量命名,格式為(成員名稱1:成員值1,成員名稱2:成員值2,……),調(diào)用的時(shí)候可以使用名稱調(diào)用:
letmessage=(name:"
小明
",age:9,grade:"
三年二班
")
letshowName=
letshowAge=message.age
letshowGrade=message.grade
playground中的效果如圖2.6所示,可以看到其效果和使用索引是相同的。圖2.6使用元組成員名取值另外,如果想要獲取元組中的某些重要部分加以利用,忽略一些不重要的信息時(shí),可以把元組的值傳遞到一個(gè)新的元組中;在新元組中聲明那些接受重要值的值成員,而不重要的部分使用下畫線“_”表示忽略。比如在上例中,只關(guān)心學(xué)生信息中的學(xué)生姓名,那么可以使用下面的語句,元組中的成員可以直接當(dāng)作常量和變量使用:
letmessage=(name:"
小明
",age:9,grade:"
三年二班
")
let(showName,_,_)=message
print("Nameis\(showName)")
playground中的效果如圖2.7所示。圖2.7使用“_”忽略不重要的值2.2.5可選型OC中沒有可選型這種數(shù)據(jù)類型,可選型是Swift獨(dú)有的,初次接觸可選型時(shí)你可能有些許疑惑;但它是一種很精妙的數(shù)據(jù)類型,本章只做簡單介紹,第3章中將詳細(xì)介紹可選型的原理與作用。可選型用于某些不確定是否有值的情況,其有兩個(gè)返回值:具體的值和nil,nil表示空值。在Swift中,經(jīng)常會(huì)選擇可選型作為返回值來處理一些結(jié)果不確定的操作,定義可選型只需在常規(guī)類型后面加一個(gè)問號(hào)“?”即可,例如:
varage:Int?
這樣,age就被定義成一個(gè)可選型,如果它有值,就一定會(huì)返回一個(gè)Int類型的值,否則返回nil??蛇x型經(jīng)常被用作搜索或者轉(zhuǎn)型方法的返回值類型,這是因?yàn)樵谒阉骱娃D(zhuǎn)型中經(jīng)常出現(xiàn)失敗的情況,此時(shí)根據(jù)返回值就可以判斷流程是否成功。在Swift標(biāo)準(zhǔn)庫中有非常多這樣的設(shè)計(jì),你可以參考這樣的設(shè)計(jì)準(zhǔn)則。下面介紹一個(gè)轉(zhuǎn)型例子。在Swift中,String類型可以和Int類型的實(shí)例互相轉(zhuǎn)換,你可以把諸如“12”這樣的字符串轉(zhuǎn)換成Int,但是不能轉(zhuǎn)換“小明”這樣的字符串。Swift風(fēng)格的轉(zhuǎn)型使用構(gòu)造器,這使得代碼更容易理解,構(gòu)造器的知識(shí)后面會(huì)具體講解,如圖2.8所示。圖2.8可選型使用示例值得注意的是,age在定義為Int類型的可選型之后被賦予了一個(gè)默認(rèn)的初始值nil,這也是可選型的一個(gè)好處之一。Swift中的類和結(jié)構(gòu)體在初始化時(shí)其內(nèi)部的所有屬性必須被初始化,否則無法通過編譯,這也是出于安全性的考慮。把一個(gè)變量定義為可選型,在沒有賦值的情況下它會(huì)被默認(rèn)賦值為nil;所以即便定義age的時(shí)候不賦值,它也已經(jīng)被初始化了,它的值是nil,直到你通過賦值更改它的值?,F(xiàn)在請(qǐng)看下面的代碼:
varage:Int?
age=Int("12")
print("ageis\(age)")
你可能認(rèn)為代碼第三行輸出的應(yīng)該是“ageis12”,但實(shí)際情況并不是這樣,如圖2.9所示。圖2.9未解包的可選型在輸出語句中我們得到age的值顯示為Optional(12),Optional代表“可選”,age的當(dāng)前值為一個(gè)整數(shù)類型的可選型。在實(shí)際開發(fā)中我們真正需要的是括號(hào)中的12,要想獲取這個(gè)12,就需要使用“解包”操作。解包是針對(duì)于可選類型的變量操作,當(dāng)我們確定一個(gè)可選型的值不為nil的時(shí)候,可以使用解包獲取其中的值。它的表現(xiàn)形式也很簡單,在需要進(jìn)行解包的變量名后面加上一個(gè)感嘆號(hào)“!”。現(xiàn)在對(duì)age變量進(jìn)行解包,效果如圖2.10所示。因?yàn)榭蛇x型對(duì)很多開發(fā)人員來說都是一個(gè)全新的概念,所以本書會(huì)在第3章中對(duì)可選型進(jìn)行更深入的講解。圖2.10對(duì)可選型進(jìn)行解包最后需要指出的是,聲明一個(gè)可選型雖然可以通過編譯器設(shè)置的安全性檢查,但是如果你不慎忘記在之后對(duì)其賦值,那么在解包的時(shí)候程序就會(huì)崩潰。即便你是個(gè)非常仔細(xì)的程序員,但是一旦聲明一個(gè)可選型就存在解包nil的可能性。聲明可選型會(huì)對(duì)我們的程序帶來風(fēng)險(xiǎn),所以我們聲明一個(gè)對(duì)象的時(shí)候,尤其是聲明類或者結(jié)構(gòu)體的屬性的時(shí)候,應(yīng)該三思而后行,盡可能為其賦初始值,當(dāng)然這個(gè)初始值應(yīng)該是明顯區(qū)別于正常值的。再把可選型轉(zhuǎn)換成非可選型的賦值語句中經(jīng)常用到“??”操作符,“??”之前為一個(gè)可選型,“??”之后為一個(gè)非可選型的值?!??”操作符自帶解包功能,在賦值時(shí)“??”會(huì)檢查其之前的可選型:如果可選型不為nil,則將其解包并返回;如果其為nil,則不會(huì)返回nil,此時(shí)返回“??”之后的非可選型的值。使用“??”改造上面的代碼,如下所示:
varage:Int//
這里避免解包,聲明age為非可選型
age=Int("12")??-1
print("ageis\(age)")//
轉(zhuǎn)型成功
age=Int("
小明
")??-1
print("ageis\(age)")//
轉(zhuǎn)型失敗
運(yùn)行結(jié)果如圖2.11所示圖2.11“??”操作符由于在真實(shí)的數(shù)據(jù)環(huán)境中年齡不可能為負(fù)數(shù),此時(shí)當(dāng)我們看到age為-1的時(shí)候就知道Int(String)轉(zhuǎn)型失敗了。相比于強(qiáng)制解包,Swift提供了一種更安全的解包方式:可選綁定。可選綁定有兩種格式可選:if-let和guard-let-else。首先來看if-let結(jié)構(gòu):
varage:Int?=Int("12")
ifleta=age{
print(a)
}
類似于if語句,當(dāng)age不為空的時(shí)候,對(duì)age解包并給其一個(gè)“別名”a,在if后的大括號(hào)對(duì)中a才有效果,此時(shí)a的值為12,已經(jīng)解包了。如果age為nil,那么大括號(hào)對(duì)中的代碼不會(huì)執(zhí)行,使用可選解包程序不會(huì)崩潰。guard-let-else是Swift2.2新引入的格式,示例如下:
varage:Int?=Int("12")
funcfindA(){
guardleta=ageelse{
return//
終止方法
}
print(a)//
在外部使用解包后的值
}
不同于if-let,guard-let-else首先處理age為nil的情況,在此種情況中必須在大括號(hào)對(duì)中使用return或者break提前終止代碼。與if-let結(jié)構(gòu)相同的是,如果age有值,那么age的值也會(huì)被保存在“別名”a中;不同的是,不管有多少個(gè)guard-let-else,別名a的作用域都在最外層,有效地避免了過于深入的嵌套。2.3基本運(yùn)算符本節(jié)將介紹Swift中的一些基本運(yùn)算符,運(yùn)算符是檢查、改變、合并值的特殊符號(hào)或短語。2.3.1賦值運(yùn)算符之前在定義常量和變量時(shí)已經(jīng)接觸過賦值運(yùn)算符的用法了,Swift使用等號(hào)“=”來表示賦值運(yùn)算。例如a=b,表示將b的值賦給了a。如果賦值的對(duì)象是一個(gè)元組,那么元組內(nèi)成員的值在賦值操作中是一一對(duì)應(yīng)的。比如let(x,y)=(1,2),則x的值會(huì)被賦為1,而y的值會(huì)被賦為2,依次類推。另外需要注意的一點(diǎn)是,如果你做過C語言的開發(fā),那么一定犯過這樣的錯(cuò)誤,在判斷語句if中本該使用“==”進(jìn)行判斷操作,但是誤寫成了“=”,造成了if判斷永真的情況。Swift為了避免這種情況發(fā)生,其賦值語句是沒有返回值的,也就是說,如果你使用如下語句:
ifx=y{}
系統(tǒng)會(huì)直接提示錯(cuò)誤,避免開發(fā)人員犯設(shè)計(jì)性的錯(cuò)誤。2.3.2數(shù)值運(yùn)算Swift支持基本的加減乘除和求余運(yùn)算,并且Swift中的數(shù)值運(yùn)算與OC相比更加強(qiáng)大。比如Swift中的加法操作“+”除了可以用來對(duì)整數(shù)和浮點(diǎn)數(shù)做加法,還可以直接拼接字符串。Swift中的求余運(yùn)算“%”可以對(duì)浮點(diǎn)數(shù)求余,這些都是C語言和OC所不具備的,示例代碼如圖2.12所示。圖2.12Swift中的數(shù)值運(yùn)算2.3.3自增和自減運(yùn)算為了幫助開發(fā)人員提前修改代碼以適應(yīng)Swift語言的迭代,Swift3.0中確定將要發(fā)生的語法改變會(huì)在Swift2.2中以警告的形式出現(xiàn),自增自減就是其中之一。Swift2.2中仍舊可以使用“++”和“--”這樣C語言風(fēng)格的操作符進(jìn)行自加和自減的操作,但是這兩個(gè)操作符會(huì)在Swift3.0之后的版本中被刪除;所以為了避免不必要的麻煩,進(jìn)行自加或自減應(yīng)使用下面的寫法:
vara=1
a+=1//
自增
a-=1//
自減
相比于我們熟悉的“++”和“--”,上面的寫法還可以指定自增和自減的“步長”,從代碼風(fēng)格統(tǒng)一的角度出發(fā),“++”和“--”確實(shí)顯得冗余了。2.3.4復(fù)合賦值Swift提供把運(yùn)算符和賦值復(fù)合起來使用的復(fù)合操作,與自增和自減操作類似,a+=2的操作等同于a=a+2,示例代碼如圖2.13所示。圖2.13復(fù)合賦值操作2.3.5比較運(yùn)算所有標(biāo)準(zhǔn)C中的比較運(yùn)算符在Swift中都可以使用。另外,在Swift中,“==”可以用在任何類型的比較中,而不用像OC中那樣使用不同的isEqual方法。比較運(yùn)算會(huì)返回Bool類型的比較結(jié)果。示例如圖2.14所示。圖2.14Swift中的比較運(yùn)算2.3.6三元運(yùn)算符前面展示的都是二元運(yùn)算符,下面介紹三元運(yùn)算符。不同于二元運(yùn)算符的加減乘除,三元運(yùn)算符有三個(gè)參與對(duì)象,格式為:判斷條件?為真時(shí)的操作:為假時(shí)的操作。它可以通過一個(gè)Bool類型判斷條件的真假來選擇執(zhí)行哪個(gè)操作,三元運(yùn)算符是if-else結(jié)構(gòu)的一種簡化。比如下面的情況,小明有一個(gè)遠(yuǎn)房王叔叔并不認(rèn)識(shí)小明和他的哥哥小剛,但是王叔叔知道小明的身高不足160(cm),而小剛的身高要高于160(cm)?,F(xiàn)在王叔叔見到了一個(gè)身高180(cm)的男孩,那么不需要自我介紹,王叔叔通過身高就可以判斷這個(gè)男孩是小剛而不是小明。這個(gè)判斷過程就對(duì)應(yīng)了一個(gè)三元運(yùn)算,如圖2.15所示。圖2.15三元運(yùn)算符判斷過程2.3.7邏輯運(yùn)算符Swift中的邏輯運(yùn)算符的操作對(duì)象是布爾值。沿用了C語言中的三種邏輯運(yùn)算:與、或、非。在工程中我們可以對(duì)布爾類型的篩選條件做邏輯運(yùn)算來判斷代碼的執(zhí)行段。示例如圖2.16所示。圖2.16邏輯運(yùn)算“邏輯與”運(yùn)算使用“&&”符號(hào)表示,可以有多個(gè)條件同時(shí)參與運(yùn)算,比如a&&b&&c……;只要其中有一個(gè)條件的布爾值為false,那么整個(gè)結(jié)果就為false,否則為true?!斑壿嫽颉边\(yùn)算使用“||”符號(hào)表示,同樣可以有多個(gè)條件同時(shí)參與運(yùn)算,比如a||b||c……;只要其中有一個(gè)條件的布爾值為true,那么整個(gè)結(jié)果就為true,否則為false。“邏輯非”運(yùn)算使用“!”符號(hào)表示,非運(yùn)算的結(jié)果總與“!”符號(hào)后面的布爾值相反。2.3.8范圍在OC中,我們可以使用Range函數(shù)來指示一個(gè)起始位置和長度,從而框定一個(gè)范圍。Swift中的范圍使用起來要方便得多,有兩種形式:1…5表示閉區(qū)間[1,5],也就是從1到5的范圍。1..<5表示半閉區(qū)間[1,5),也就是從1到4。范圍經(jīng)常會(huì)和for-in循環(huán)語句連用,比如下面的形式:
forindexin1...5
{
println(index)
}
也可以用在switch控制流的case中,在后面講到switch時(shí)會(huì)講解,基本形式如下:
varindex=3
switchindex{
case1...2:
print("Hello")
case3...4:
print("World")
default:break
}
2.3.9括號(hào)優(yōu)先級(jí)為了保持運(yùn)算的先后順序,可以使用括號(hào)來指示優(yōu)先級(jí)。比如運(yùn)算a*(b+c),雖然乘法的優(yōu)先級(jí)高于加法,但是由于使用了括號(hào)來指示優(yōu)先級(jí),所以首先進(jìn)行b+c的運(yùn)算,然后其結(jié)果再與a相乘,與數(shù)學(xué)上的運(yùn)算順序相同。除數(shù)值運(yùn)算外,括號(hào)也可以用在邏輯運(yùn)算中,比如a&&(b||c),表示首先進(jìn)行括號(hào)中的或運(yùn)算,然后其結(jié)果再與a做與運(yùn)算。2.4字符串與字符在Swift中,字符串的類型是String,不論定義的是常量字符串還是變量字符串。
letdontModifyMe="
請(qǐng)不要修改我
"
varmodifyMe="
你可以修改我
"
而在OC中,你需要使用NSString和NSMutableString來區(qū)分字符串是否可以被修改。前面我們講過,在Swift中,連接兩個(gè)字符串組成新字符串非常方便,使用“+”即可,如圖2.17所示。圖2.17使用“+”拼接字符串在OC中我們要實(shí)現(xiàn)同樣的拼接只能使用stringWithFormat方法,做法如下:
NSString*firstMessage=@"Swift
很不錯(cuò)
.";
NSString*secondMessage=@"
你覺得呢
?";
NSString*message=[NSStringstringWithFormat:@"%@%@",firstMessage,
secondMessage];
NSLog(@"%@",message);
在OC中,判斷兩個(gè)字符串是否相同時(shí)不能用“==”,而要使用方法isEqualToString,但在Swift中完全可以使用“==”來判斷字符串是否相同。
letstring1="Hello"
letstring2="Hello"
ifstring1==string2{
print("
二者相同
")
}
處理字符串的難點(diǎn)是字符串的索引和字符串的創(chuàng)建,以及如何創(chuàng)建一個(gè)字符串的子串。字符串由Unicode組成,但是不能把Unicode組成的字符串的子串看作Unicode字符,而是把它們拆分成Unicode字素。我們不能像在數(shù)組中那樣使用整數(shù)作為下標(biāo)索引,因?yàn)闀?huì)遇到有的字素是由多個(gè)字符組成的情況,這樣會(huì)把一個(gè)完整語義的字素拆成兩個(gè)字符,從而改變了原意。例如,法語中有重音符號(hào),一個(gè)à是一個(gè)完整的字素,這個(gè)字素由兩個(gè)Unicode字符組成,如果按照Unicode字符來索引就會(huì)破壞語言的結(jié)構(gòu)。所以字符串是由另外的一個(gè)類型來索引的,這個(gè)類型就是String.Index。在Swift2.2中,想要獲得String中某個(gè)字素的時(shí)候,應(yīng)使用函數(shù)advance;其中有兩個(gè)參數(shù),stratIndex指定String的第一個(gè)字素,第二個(gè)參數(shù)指定步長。函數(shù)會(huì)返回一個(gè)String.Index類型,這是一個(gè)字符串的字素位,我們可以使用這個(gè)字素位來插入或者刪除String中的元素,用法如圖2.18所示。圖2.18獲取字符串的String.Indexadvance會(huì)跳過整個(gè)字素而不是一個(gè)字符。如圖2.18所示,index為String.Index類型,和數(shù)組類型一樣,String類型支持下標(biāo)操作。首先指定起始是從頭部開始,還是從尾部開始;頭部開始調(diào)用startIndex,尾部開始調(diào)用endIndex。然后調(diào)用advancedBy指定“步長”,“步長”使用整型格式。上例中指定了“步長”為3,通過startIndex和advancedBy組合生成了一個(gè)字符串頭部字素后面的第三個(gè)字素的下標(biāo)(下標(biāo)的具體用法會(huì)在后面講到),通過下標(biāo)取值返回的是l,證明“à”作為一個(gè)完整的字素被跳過了。受Swift3.0中函數(shù)語法變動(dòng)的影響,String中的API也發(fā)生了一些變化,Swift3.0中取下標(biāo)的API統(tǒng)一使用index方法:
varstr="Heàllo"
str[str.index(str.startIndex,offsetBy:3)]
需要注意的是,下標(biāo)取值并不能保證安全,如果下標(biāo)超出了字符串末尾字符的下標(biāo),那么程序會(huì)掛掉。String提供了一個(gè)編譯期檢查下標(biāo)是否越界的API,用法如下:
str[str.startIndex.advancedBy(6,limit:str.endIndex)]
Swift3.0中的版本為:
str[str.index(str.startIndex,offsetBy:6,limitedBy:str.endIndex)!]
一旦你指定的下標(biāo)越界就會(huì)立即拋出錯(cuò)誤。最后我們使用之前講到的范圍來截取str的子串,在截取起始終止位置的時(shí)候不能直接用Int類型,而是必須采用advance的辦法,做法如圖2.19所示,示例中最后截取的子串為“e3à”。圖2.19截取子串你可能會(huì)覺得這樣的用法非常麻煩,然而這也正是Swift語言進(jìn)步的原因之一。同理,Swift3.0中需要使用下面的格式:
varstr="Heàllo"
letstart=str.index(str.startIndex,offsetBy:1)
letend=str.index(str.startIndex,offsetBy:3)
str[start...end]
OC中的NSString類型無非處理多個(gè)字符組成的字素,在Swift1.2版本中,弱化了String和NSString的關(guān)聯(lián),因此無法直接把一個(gè)NSString類型的值遞給一個(gè)String類型的變量;但是在Swift2.0之后,重新建立了NSString和String之間的橋接。由于String是比NSString更高級(jí)的對(duì)象,因此把NSString對(duì)象賦值給String對(duì)象時(shí)需要使用構(gòu)造器進(jìn)行轉(zhuǎn)換,而String賦值給NSString對(duì)象時(shí)可以直接賦值,如圖2.20所示。圖2.20NSString與String的轉(zhuǎn)換不過在Swift3.0版本中,String與NSString之間的傳值需要遵循嚴(yán)格的類型轉(zhuǎn)化:
vars1:NSString="NSStr"
vars2:String=String(s1)
vars3:String="Str"
vars4:NSString=s3asNSString//
需要轉(zhuǎn)類型
字符串中還有很多有用的方法,比如rangeOfString會(huì)返回一個(gè)可選類型的范圍Range<String.Index>。我們可以使用這個(gè)方法獲得一個(gè)浮點(diǎn)數(shù)的整數(shù)部分,代碼如下:
letnum="123.45"
letdeRange=num.rangeOfString(".")//
該方法返回的是可選型
letwholeNumber=num[num.startIndex..<deRange!.startIndex]
playground中的結(jié)果如圖2.21所示。圖2.21使用rangeOfString獲得一個(gè)浮點(diǎn)數(shù)的整數(shù)部分Swift3.0中,rangeOfString遵照新的命名格式:
letnum="123.45"
letdeRange=num.range(of:".")//
該方法返回的是可選型
letwholeNumber=num[num.startIndex..<deRange!.lowerBound]
并且你可以看到String的Range不再提供startIndex這個(gè)參數(shù),取而代之的是新的命名lowerBound,與String的startIndex作出區(qū)分。此外還可以替換或者刪除字符串中的某部分,刪除子串可以使用removeRange方法:
varstr="Hello"
letstartIndex=str.startIndex.advancedBy(1)//
字母
e
letendIndex=str.startIndex.advancedBy(3)//
第二個(gè)字母
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中單個(gè)字素是Character類型的,刪除單個(gè)字素的方法是removeAtIndex。注意,無論是刪除整段還是單個(gè)字素,方法的參數(shù)類型都是String.Index。下面是刪除單個(gè)字素的示例:
varstr="Hello"
letstartIndex=advance(str.startIndex,1)
str.removeAtIndex(startIndex)
print(str)
playground中的運(yùn)行結(jié)果如圖2.23所示。圖2.23removeAtIndex方法的使用Swift3.0版本:
varstr="Hello"
letstart=str.index(str.startIndex,offsetBy:1)
str.remove(at:start)
print(str)
替換子字符串的方法與刪除類似,有兩個(gè)參數(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中運(yùn)行結(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ù)組的時(shí)候會(huì)介紹這些方法,一起見證Swift語言的神奇。2.5集合類型Swift中有三種集合類型——數(shù)組、集合和字典,其中集合是Swift1.2版本加入的新成員。Swift中的數(shù)組用來順序存儲(chǔ)相同類型的數(shù)據(jù),數(shù)組成員可以重復(fù)。集合類型的概念類似于我們?cè)跀?shù)學(xué)中所學(xué)的集合;和數(shù)組一樣,Swift中的集合也是用來順序存儲(chǔ)相同類型的數(shù)據(jù),但是集合成員不能重復(fù)。字典類型雖然無序,但是要求存儲(chǔ)的成員必須是相同的類型,字典中的成員使用“鍵值對(duì)”格式。2.5.1數(shù)組OC中的數(shù)組分為NSArray和NSMutableArray兩種,分別表示不可變的數(shù)組和可變的數(shù)組,這兩種數(shù)組類型都可以存儲(chǔ)任何類型的實(shí)例。Swift中的數(shù)組使用Array關(guān)鍵字定義,或者使用類型推斷來初始化;Swift中的數(shù)組是類型安全的,數(shù)據(jù)值在被存入數(shù)組之前類型必須明確。通常定義一個(gè)數(shù)組使用var關(guān)鍵字,如果使用let關(guān)鍵字,則證明數(shù)組是一個(gè)常量,將不能使用方法來增加或者刪除這個(gè)數(shù)組中的元素。如果數(shù)組中只有四個(gè)元素,而你要訪問第五個(gè)元素,那么會(huì)拋出運(yùn)行時(shí)錯(cuò)誤,提示數(shù)組越界。創(chuàng)建一個(gè)數(shù)組的實(shí)例有兩種方式,第一種方式如下:
vara=Array<String>()//
得到一個(gè)字符串類型的空數(shù)組
這是一種泛型結(jié)構(gòu)體式的初始化方法。簡單講一下泛型的相關(guān)知識(shí),一個(gè)數(shù)組中的值必須是相同類型的,但我們的數(shù)組可以選擇全部存儲(chǔ)整數(shù),也可以選擇全部存儲(chǔ)浮點(diǎn)數(shù)。比如上面的代碼中創(chuàng)建了一個(gè)存儲(chǔ)字符串的數(shù)組實(shí)例。由于這種類型的不確定性,所以將數(shù)組定義為Array<T>,如果給T賦不同類型的值,那么創(chuàng)建的就是不同值類型的數(shù)組。第二種方式如下,和第一種方式是等價(jià)的:
vara=[String]()
這種形式更加簡潔,也是官方推薦的寫法,在日常開發(fā)中建議使用這種寫法。而在OC中,因?yàn)锳rray是引用類型(有關(guān)值類型和引用類型的知識(shí),會(huì)在后面講到),為了避免“共享”問題的出現(xiàn),創(chuàng)建一個(gè)可變數(shù)組的代碼要復(fù)雜一些:
NSArray*exampleOfNSArray=@[@"
糖醋里脊
",@"
宮保雞丁
",@"
水煮魚
",@"
魚香肉絲
",@"
大盤雞
"];
NSMutableArray*exampleOfNSMutableArray=[[NSMutableArrayalloc]
initWithArray:exampleOfNSArraycopyItems:YES];
在Swift中建立一個(gè)數(shù)組的代碼如下,這一次我們使用了類型推斷:
varexampleOfArray=["
糖醋里脊
","
宮保雞丁
","
水煮魚
","
魚香肉絲
","
大盤雞
"]
和NSArray相似,Swift中的Array也有很多有用的屬性,比如只讀屬性count返回?cái)?shù)組中的元素個(gè)數(shù),效果如圖2.25所示。圖2.25查看數(shù)組的count屬性在OC中,可以使用NSMutableArray中的方法addObject來增加數(shù)組中的元素;而Swift中的方法更簡單,可以使用“+=”,比如給之前的數(shù)組增加一個(gè)元素:
exampleOfArray+=["AD
鈣奶
"]
注意,這個(gè)方法是數(shù)組間的,也就是說,只要數(shù)組類型相同,就可以把一個(gè)數(shù)組中的元素加入到另一個(gè)數(shù)組中。如果只是一個(gè)單個(gè)元素要加入數(shù)組中,則需要在元素外面加上[],新元素會(huì)加在數(shù)組的尾部,效果如圖2.26所示。圖2.26使用“+=”向數(shù)組中加入新元素當(dāng)然也可以使用其他方法向數(shù)組中添加元素,比如使用append方法可以達(dá)到和“+=”相同的目的。下面向數(shù)組尾部增加一個(gè)元素:
exampleOfArray.append("AD
鈣奶
")
要取出或者替換數(shù)組中的元素,需要使用下標(biāo)索引,這一點(diǎn)與OC相同。數(shù)組中的索引從0開始,代碼如下所示:
vararrayItem=exampleOfArray[0]
exampleOfArray[1]="
宮保山藥
"
可以使用范圍來獲取或者替換數(shù)組中的多個(gè)元素,替換的元素和原有的元素個(gè)數(shù)可以不同:
exampleOfArray[1...2]=["AD
鈣奶
"]
上面的代碼中使用一個(gè)元素替換了原數(shù)組中的兩個(gè)元素,替換之后數(shù)組的長度也發(fā)生了變化,效果如圖2.27所示。圖2.27替換數(shù)組中的多個(gè)元素在數(shù)組的下標(biāo)中,使用范圍返回的結(jié)果是該數(shù)組的一個(gè)“片段”,該片段不會(huì)占用額外的存儲(chǔ)空間,而只是代表了原數(shù)組的某個(gè)數(shù)據(jù)段。如果想把新元素插入到指定位置,則可以使用方法insert:
exampleOfArray.insert("AD
鈣奶
",atIndex:3)
效果如圖2.28所示。圖2.28使用insert方法向數(shù)組指定位置插入元素參數(shù)atIndex指定新元素在數(shù)組中的位置。注意,索引是從0開始的,因此圖2.28中的代碼是指在數(shù)組的第四個(gè)位置插入新元素“AD鈣奶”;被插入位置上原來的元素及之后的元素會(huì)向后移動(dòng),數(shù)組的長度會(huì)增加1。Swift3.0版本的插入方法使用了更簡潔的參數(shù)命名:
exampleOfArray.insert("AD
鈣奶
",at:3)
可以使用removeLast方法刪除數(shù)組的最后一個(gè)元素:
exampleOfArray.removeLast()
也可以使用removeAtIndex方法刪除指定位置的元素:
exampleOfArray.removeLast()
Swift3.0版本:
exampleOfArray.remove(at:0)
分別使用上面兩個(gè)方法刪除了數(shù)組的最后一個(gè)和第一個(gè)元素,效果如圖2.29所示。圖2.29刪除不同位置的元素需要注意的是,與字典中“搜索”性質(zhì)的方法不同,數(shù)組中的許多方法是基于下標(biāo)的,也就是說,這些方法不會(huì)返回可選型的值。比如上面提到的removeLast方法,如果對(duì)一個(gè)空數(shù)組調(diào)用removeLast方法會(huì)導(dǎo)致“越界”。為了避免這樣的情況,在使用這些方法時(shí)最好首先判斷邊界條件,比如:
if!b.isEmpty{
b.removeLast()
}
2.5.2集合集合和數(shù)組非常相似,區(qū)別是集合中不會(huì)有重復(fù)的元素,并且集合中的成員是無序的。有些情況下我們需要數(shù)組中的值不包含相同的元素,這個(gè)時(shí)候就需要使用集合。我們可以把一個(gè)數(shù)組轉(zhuǎn)換成集合,方法如下:
varexampleOfArray=["
糖醋里脊
","
宮保雞丁
","
水煮魚
","
魚香肉絲
","
大盤雞
","
大盤雞
"]
varexampleOfSet=Set(exampleOfArray)
或者把變量聲明為集合??梢允褂靡粋€(gè)數(shù)組樣式的字面量來初始化集合,這樣在給這個(gè)變量賦值的時(shí)候,即便數(shù)組中存在重復(fù)的元素,變量中也不會(huì)出現(xiàn)重復(fù)元素,例如:
varexampleOfSet:Set=["
糖醋里脊
","
宮保雞丁
","
水煮魚
","
魚香肉絲"
,"
大盤雞
","
大盤雞
"]
效果如圖2.30所示,集合中的元素是用大括號(hào)括起來的(和字典一樣,Swift中大括號(hào)表示一種無序),這和我們?cè)跀?shù)學(xué)上學(xué)到的集合的表示方法相同。因?yàn)榇罄ㄌ?hào)和閉包的格式?jīng)_突了,所以無法用大括號(hào)括起元素的方法作為字面量來初始化一個(gè)集合,所以必須借助數(shù)組的格式,并且需要將變量顯式地聲明為集合。數(shù)組和集合都可以使用中括號(hào)格式的字面量做初始化,其實(shí)是因?yàn)槎叨甲袷亓薃rrayLiteralConvertible協(xié)議,這個(gè)協(xié)議的相關(guān)知識(shí)會(huì)在第3章中介紹。圖2.30聲明一個(gè)集合集合也有許多方法,我們需要了解的是添加和刪除元素的方法,這些方法都有返回值。
exampleOfSet.insert("AD鈣奶")//
新增一個(gè)元素
exampleOfSet.remove("AD鈣奶")//
刪除一個(gè)元素
由于集合中不存在重復(fù)的元素,并且集合是無序的,因此在刪除元素時(shí)不需要指定下標(biāo),只需指定元素的名稱即可。如果集合中沒有該元素,則remove方法會(huì)返回nil。集合的最廣泛應(yīng)用是求多個(gè)集合的交集、差集、并集和補(bǔ)集,這些都是數(shù)學(xué)上的概念,本書不做詳細(xì)介紹,圖2.31給出了兩個(gè)集合的運(yùn)算示例。圖2.31兩個(gè)集合的運(yùn)算示例2.5.3字典字典有點(diǎn)類似于數(shù)組,它的鮮明特征是鍵值對(duì)[Key,Value]。和數(shù)組一樣,字典的創(chuàng)建也有兩種方式:
varexampleOfDictionary=Dictionary<String,Int>()
等同于:
varexampleOfDictionary=[String:Int]()
很明顯字典的定義也是泛型的,值的部分是完全的泛型,鍵的部分雖然是泛型的,但是要求該泛型必須遵守Hashable協(xié)議。對(duì)泛型的作用范圍進(jìn)行約束,也是協(xié)議的職責(zé)之一。本書的核心是面向協(xié)議編程,會(huì)在后面的章節(jié)重點(diǎn)介紹協(xié)議的用法,這里只做了解。我們可以使用鍵來索引任意類型的值,但是和數(shù)組一樣,一個(gè)字典中的值必須是同一種類型。我們使用鍵來訪問值,如果鍵不在字典中,那么就會(huì)返回一個(gè)nil。這點(diǎn)很好理解,就如字面意思那樣,我們遇到不認(rèn)識(shí)的字時(shí)會(huì)去查字典,結(jié)果可能查到也可能沒查到,本質(zhì)是一個(gè)“搜索”過程。我們可以使用類型推斷來新建一個(gè)字典:
varexampleOfDictionary=["
年齡
":25,"
身高
":175]
同樣的字典在OC中的創(chuàng)建方式如下:
NSDictionary*exampleOfDictionary=@{@"
年齡
":@25,@"
身高
":@175};
這里使用了字面量的方式來創(chuàng)建一個(gè)NSDictionary,由于NSDictionary中只能使用OC中的對(duì)象,所以數(shù)字要轉(zhuǎn)換成NSNumber。使用字面量的方式只需在數(shù)字前面加上“@”即可。和數(shù)組一樣,我們可以使用只讀屬性count來獲取字典中鍵值對(duì)的數(shù)量,如圖2.32所示。圖2.32字典中的count屬性如果想要獲取或者修改字典中的值,則可以使用鍵來索引,形式如下:
exampleOfDictionary["
年齡
"]=20
添加一個(gè)新鍵值對(duì)的形式和上面的代碼類似,如果賦值語句中字典的鍵值之前沒有存儲(chǔ)在字典當(dāng)中,則會(huì)將這個(gè)鍵值對(duì)自動(dòng)添加到字典中,如圖2.33所示。圖2.33修改和添加鍵值對(duì)使用字典的updateValue方法可以達(dá)到同樣的目的,不過這個(gè)方法會(huì)返回修改前的值;如果修改的鍵之前不存在于字典中,則會(huì)新增這個(gè)鍵值對(duì),同時(shí)返回nil,如圖2.34所示。圖2.34使用updateValue方法獲取舊值可以使用下標(biāo)的方法來移除字典中的鍵值對(duì),只需給某個(gè)鍵對(duì)應(yīng)的值賦值為nil即可,如圖2.35所示。圖2.35使用下標(biāo)方法刪除鍵值對(duì)同樣,使用removeValueForKey方法(Swift3.0中為removeValue(forKey:))可以達(dá)到同樣的目的,與updateValue一樣,removeValueForKey方法會(huì)返回被刪除的值,如圖2.36所示。圖2.36使用removeValueForKey方法刪除鍵值對(duì)2.6控制流Swift中的控制流非常強(qiáng)大,既可以使用for和while語句進(jìn)行多次循環(huán),也可以使用if、guard和switch進(jìn)行判斷后執(zhí)行分支代碼。與控制流相關(guān)的一個(gè)重要知識(shí)點(diǎn)是模式匹配,本書會(huì)在第3章中專門講解。2.6.1for循環(huán)在Swift中,最常使用的for循環(huán)是for
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 中國農(nóng)村醫(yī)療保障制度的補(bǔ)償模式研究
- 鞍鋼集團(tuán)有限公司介紹
- 2025 除夕傳統(tǒng)文化介紹
- 二零二五年度區(qū)塊鏈合伙人退伙共識(shí)機(jī)制契約3篇
- 2025商業(yè)地產(chǎn)蛇年國潮新春廟會(huì)市集(敦煌非遺玩趣廟會(huì)主題)活動(dòng)策劃方案-80正式版
- 軍令狀企業(yè)誓師大會(huì)
- 五金電工知識(shí)培訓(xùn)課件
- 可降解塑料餐具、5800噸塑料托盤、托盒項(xiàng)目可行性研究報(bào)告寫作模板-申批備案
- 二零二五年度房產(chǎn)贈(zèng)與與文化遺產(chǎn)保護(hù)合同3篇
- 江西省上饒市2024-2025學(xué)年度第一學(xué)期九年級(jí)道德與法治學(xué)科期末綠色評(píng)價(jià)試卷(含答案)
- 西交大少年班英語考試試題
- 北京語言大學(xué)保衛(wèi)處管理崗位工作人員招考聘用【共500題附答案解析】模擬試卷
- 人教版七年級(jí)下冊(cè)數(shù)學(xué)全冊(cè)完整版課件
- 初中生物人教七年級(jí)上冊(cè)(2023年更新) 生物圈中的綠色植物18 開花和結(jié)果
- 水電解質(zhì)及酸堿平衡的業(yè)務(wù)學(xué)習(xí)
- CSCEC8XN-SP-安全總監(jiān)項(xiàng)目實(shí)操手冊(cè)
- 口腔衛(wèi)生保健知識(shí)講座班會(huì)全文PPT
- 成都市產(chǎn)業(yè)園區(qū)物業(yè)服務(wù)等級(jí)劃分二級(jí)標(biāo)準(zhǔn)整理版
- 最新監(jiān)督學(xué)模擬試卷及答案解析
- ASCO7000系列GROUP5控制盤使用手冊(cè)
- 污水處理廠關(guān)鍵部位施工監(jiān)理控制要點(diǎn)
評(píng)論
0/150
提交評(píng)論