簡(jiǎn)介
這是一個(gè)Swift語(yǔ)言教程,基于最新的iOS 9,Xcode 7.3和Swift 2.2,會(huì)為你介紹Swift編程非常基礎(chǔ)的內(nèi)容。從電腦如何工作的全程基本原理到語(yǔ)言結(jié)構(gòu),你會(huì)足夠了解這門(mén)語(yǔ)言,來(lái)處理數(shù)據(jù)和管理代碼的行為。

快速鏈接
- 一個(gè)下午讓你掌握Swift基礎(chǔ) ( 1/9 ) 編程本質(zhì) & Playground基礎(chǔ)
- 一個(gè)下午讓你掌握Swift基礎(chǔ) ( 2/9 ) 變量 & 常量
- 一個(gè)下午讓你掌握Swift基礎(chǔ) ( 3/9 ) 數(shù)字類(lèi)型 & 操作
- 一個(gè)下午讓你掌握Swift基礎(chǔ) ( 4/9 ) 字符串
- 一個(gè)下午讓你掌握Swift基礎(chǔ) ( 5/9 ) 做判斷
- 一個(gè)下午讓你掌握Swift基礎(chǔ) ( 6/9 ) 重復(fù)步驟
- 一個(gè)下午讓你掌握Swift基礎(chǔ) ( 7/9 ) 函數(shù)
- 一個(gè)下午讓你掌握Swift基礎(chǔ) ( 8/9 ) 閉包
- 一個(gè)下午讓你掌握Swift基礎(chǔ) ( 9/9 ) 可選值
- Swift 初學(xué)者 ( 10/12 ) 數(shù)組
- Swift 初學(xué)者 ( 11/12 ) 字典
集合
集合(set)是沒(méi)有順序的相同類(lèi)型唯一值的集合。當(dāng)你想確保一個(gè)項(xiàng)目不會(huì)在集合里出現(xiàn)多次的時(shí)候,它會(huì)變得非常有用,并且項(xiàng)目的順序并不重要。
例如,你想追蹤游戲里還有哪些選手是活躍的,就可以用集合。

你對(duì)于這里選手的順序并不感興趣;你想讓集合做的事是存儲(chǔ)人并且并不允許他們?cè)诩侠锍霈F(xiàn)兩次。然后只需要問(wèn)集合,“Alice 還在游戲里嗎?”然后預(yù)期得到一個(gè)布爾型的 true / false。
如上圖所示,沒(méi)有索引或鍵可以用來(lái)取回值。你會(huì)在這篇文章里讀到,你仍然可以遍歷集合以及查詢(xún)特定的值在不在集合里。
創(chuàng)建集合
你可以顯示聲明集合,通過(guò)寫(xiě) Set 緊接著尖括號(hào)里加上類(lèi)型:
let setOne: Set<Int>
Swift 也能從初始化的類(lèi)型里推斷集合的類(lèi)型:
let setTwo = Set<Int>()
打印 setTwo,你會(huì)發(fā)現(xiàn)有趣的東西:
print(setTwo)
// > []
它顯示了空的集合字面值和空數(shù)組的相同。
集合字面值
數(shù)組和集合不只是空的字面值相同。事實(shí)上,集合沒(méi)有自己的字面值,用數(shù)組字面值來(lái)創(chuàng)建帶有初始值的集合??催@個(gè)例子:
let someArray = [1, 2, 3, 1]
這是一個(gè)數(shù)組。那怎么用數(shù)組字面值創(chuàng)建集合呢?像這樣:
let someSet: Set<Int> = [1, 2, 3, 1]
你需要顯示聲明變量為一個(gè) Set。但是,感謝 Swift 的類(lèi)型推斷,你可以忽略集合包含的值類(lèi)型:
let anotherSet: Set = [1, 2, 3, 1]
很明顯,這是整數(shù)集合,所以不需要定義集合的類(lèi)型。
要用行動(dòng)看一下集合最重要的特色,讓我們打印一下你剛剛創(chuàng)建的集合:
print(someSet)
// > [2, 3, 1]
首先,可以看到?jīng)]有特定的順序。其次,盡管你創(chuàng)建的集合帶有兩個(gè)實(shí)例值為 1,但這個(gè)值只出現(xiàn)了一次——記住,集合的值必須是唯一的。
訪問(wèn)元素
集合里的元素沒(méi)有索引或鍵,所以你怎么知道集合到底有沒(méi)有元素呢,以及怎么訪問(wèn)它擁有的任意元素?就像數(shù)組和字典,集合支持 count 和 isEmpty properties。
print(someSet.isEmpty)
// > false
print(someSet.count)
// > 3
可以使用 contains(_:) 來(lái)檢查特定元素是否存在:
print(someSet.contains(1))
// > true
print(someSet.contains(4))
// > false
你也可以使用 first 和 last properties,返回集合里的一個(gè)元素。但是,因?yàn)榧蠜](méi)有順序,你無(wú)法確切知道會(huì)獲得哪個(gè)項(xiàng)目。盡管對(duì)于尺寸為 0 或 1 的集合,這會(huì)是一個(gè)獲取單一集合元素的快捷方式。
print(someSet.first)
// > Optional(2)
就像預(yù)料的,frist 返回了可選值。它必須這樣做因?yàn)榧峡赡苁强盏模谶@種情況下 property 會(huì)返回 nil。
添加和移除元素
回到紙牌游戲。你想為明天規(guī)劃一個(gè)游戲,希望選擇一個(gè)對(duì)所有人對(duì)方便的時(shí)間。從建議你自己的適宜時(shí)間開(kāi)始:
var myTimes: Set = ["8am", "9am", "10am"]
你把這個(gè)集合聲明為變量,因?yàn)槠每赡軙?huì)改變。例如,假設(shè)你決定上午 11 點(diǎn)也是開(kāi)始游戲的耗時(shí)間,那就給集合添加另一個(gè)元素:
myTimes.insert("11am")
print(myTimes)
// > ["9am", "8am", "11am", "10am"]
insert(_:) 添加了元素到集合;如果元素已經(jīng)存在,方法什么都不會(huì)做。
你意識(shí)到上午 8 點(diǎn)太早了。你可以像這樣從集合里移除元素:
let removedElement = myTimes.remove("8am")
print(removedElement)
// > Optional("8am")
remove(_:) 返回被移除的元素,如果它在集合里的話,否則就是 nil。
迷你練習(xí)
寫(xiě)一個(gè)函數(shù)移除整數(shù)數(shù)組里的所有重復(fù)。數(shù)組?你想問(wèn)這篇不是關(guān)于集合的嗎?
小提示:數(shù)組有一個(gè)用 Set 類(lèi)型的初始化,集合有一個(gè)用 Array 類(lèi)型的初始化。
遍歷集合
當(dāng)你想遍歷集合的元素的時(shí)候用 for-in 循環(huán):
for element in myTimes {
print(element)
}
// > 9am
// > 11am
// > 10am
可以預(yù)料,結(jié)果沒(méi)有預(yù)先設(shè)置的順序。然而,這和你在其它集合類(lèi)型里看到的 for-in 語(yǔ)法相似。
集合操作
集合最強(qiáng)大的特色之一就是他們支持集合操作(set operations),允許你把兩個(gè)集合組成一個(gè),創(chuàng)建只有兩個(gè)或更多集合的共同值的集合。讓我們用你的偏好時(shí)間集合來(lái)檢測(cè)這些操作,以及另一組時(shí)間。
提醒一下,你提議了游戲時(shí)間為上午 9 點(diǎn),10 點(diǎn)或 11 點(diǎn)。Adam 給你發(fā)送了他的偏好時(shí)間:
let adamTimes: Set = ["9am", "11am", "1pm"]
讓我們依次看看集合操作的四個(gè)類(lèi)型。
Union
union(_:) 創(chuàng)建新集合,帶有兩個(gè)集合所有的值:
let unionSet = myTimes.union(adamTimes)
print(unionSet)
// > ["9am", "11am", "10am", "1pm"]
主要要注意盡管你和 Adam 都選擇了上午 9 點(diǎn) 和 上午 11 點(diǎn)為見(jiàn)面好時(shí)間,這些值在新集合只出現(xiàn)了一次。
這里,你留下了你和 Adam 提議的每個(gè)時(shí)間。
Intersect
intersect(_:) 創(chuàng)建新集合,只帶有兩個(gè)集合的共同值。你可以用它創(chuàng)建基于你和 Adam 同意的時(shí)間集合。
let intersectSet = myTimes.intersect(adamTimes)
print(intersectSet)
// > ["9am", "11am"]
這里,結(jié)果集合里的值就是在 myTimes 和 adamTimes 集合里同時(shí)出現(xiàn)的那些。
Subtract
subtract(_:) 創(chuàng)建新集合,移除在第二個(gè)集合里出現(xiàn)的值。
let subtractSet = myTimes.subtract(adamTimes)
print(subtractSet)
// > ["10am"]
從 myTimes 里的所有時(shí)間開(kāi)始。然后 subtract(:_) 移除了 adamTimes 里出現(xiàn)的所有時(shí)間,留下只有你提議、Adam 沒(méi)有提議的時(shí)間。
這個(gè)例子里,上午 10 點(diǎn)是唯一的你提議但沒(méi)有被 Adam 也提議的時(shí)間。
Exclusive Or
exclusiveOr(_:) 創(chuàng)建新集合,帶有只在一個(gè)集合出現(xiàn)的值,不包括同時(shí)具有的。
let exclusiveOrSet = myTimes.exclusiveOr(adamTimes)
print(exclusiveOrSet)
// > ["10am", "1pm"]
這些是你提議但 Adam 沒(méi)有提議的開(kāi)始時(shí)間,以及 Adam 提議而你沒(méi)有的開(kāi)始時(shí)間。

迷你練習(xí)
快速回答:你會(huì)用哪個(gè)集合操作來(lái)找到見(jiàn)面的合適時(shí)間?
集合操作的運(yùn)行時(shí)間
集合和字典有非常相似的實(shí)現(xiàn),他們也需要元素可以被哈希。所有操作的運(yùn)行時(shí)間都和字典的那些相同。
關(guān)鍵點(diǎn)
- 集合(Sets)是相同類(lèi)型的唯一值的無(wú)序集合。
- 集合在你需要知道一些東西是不是被包含在集合里的時(shí)候最有用處。
- 可以從數(shù)組初始化集合,反之亦然。
- 集合操作(Set operations)很強(qiáng)力,允許你處理潛在的大量數(shù)據(jù)來(lái)組合和過(guò)濾元素。
接下來(lái)去哪兒?
既然你現(xiàn)在已經(jīng)學(xué)習(xí)了 Swift 里的三種集合類(lèi)型,你應(yīng)該很了解他們能做什么以及何時(shí)該使用它們。你在繼續(xù)讀教程的時(shí)候會(huì)看到出現(xiàn)。
現(xiàn)在你知道怎么把數(shù)組組合進(jìn)數(shù)組、字典和集合里了,本教程的下一個(gè)部分涉及了命名類(lèi)型(named types)。他們?cè)试S你同時(shí)組合數(shù)據(jù)和代碼到一起,放到自定義的類(lèi)型里,作為更大和更好的東西的建筑塊!
移步之前,看看下面的挑戰(zhàn)來(lái)測(cè)試你的集合知識(shí)。
挑戰(zhàn)
挑戰(zhàn) A:你就是編譯器
下列哪個(gè)為有效語(yǔ)句?
1. let set1: Set<Int> = [1]
2. let set2 = [1]
3. let set3 = Set<Int>()
對(duì)于接下來(lái)的三條語(yǔ)句,使用這個(gè)集合:
let set4: Set = [1, 2, 3]
4. set4[1]
5. set4.insert(1)
6. set4.contains(1)
對(duì)于接下來(lái)的兩條語(yǔ)句,使用這個(gè)集合:
var set5: Set = [1, 2, 3]
7. set5.insert("1")
8. set5.remove(1)
挑戰(zhàn) B:檢測(cè)集合包含的項(xiàng)目
假設(shè)你有 10,000 個(gè)人的郵箱地址集合:let emails: Set<String>。寫(xiě)一個(gè)函數(shù),如果給定的郵箱地址在集合里就返回 true,否則 false。不允許用 contains(_:) 或遍歷集合。
挑戰(zhàn) C:追蹤到場(chǎng)人數(shù)
你是 Swift 大學(xué)里的教授,在教一個(gè)為期三天的課程。每天,你追蹤到場(chǎng)人數(shù),通過(guò)到場(chǎng)的每個(gè)學(xué)生的名字到新的集合里。
例如:
let day1: Set = ["Anna", "Benny", "Charlie"]
let day2: Set = ["Anna", "Benny", "Danny"]
let day3: Set = ["Anna", "Danny", "Eric"]
- 寫(xiě)一個(gè)函數(shù),返回三天都到了的學(xué)生的集合。
- 寫(xiě)一個(gè)函數(shù)判斷誰(shuí)在課程的第一天之后退出了。
這兩個(gè)函數(shù)的結(jié)構(gòu)為:
func funcName(day1: Set<String>, day2: Set<String>, day3: Set<String>) ->Set<String>
挑戰(zhàn)和迷你練習(xí)源代碼
https://yunpan.cn/cMQMgQ3itt7fy (提取碼:6680)
介紹
歡迎來(lái)到Swift世界!Swift是一門(mén)蘋(píng)果在2014年夏天發(fā)布的編程語(yǔ)言。從那之后,Swift發(fā)布了一個(gè)主要的版本跳躍,成為了開(kāi)始在蘋(píng)果平臺(tái):iOS,OS X,watchOS和tvOS開(kāi)發(fā)的最簡(jiǎn)單的方式。
誰(shuí)適合這篇教程
這篇教程適合懂一點(diǎn)編程、并且希望學(xué)習(xí)Swift的人。也許你已經(jīng)為網(wǎng)站寫(xiě)過(guò)一些JavaScript代碼,或者用Python寫(xiě)過(guò)一些簡(jiǎn)短的程序。這篇教程就是為你準(zhǔn)備的!你會(huì)學(xué)習(xí)到編程的基本概念,同時(shí)也會(huì)成為Swift語(yǔ)言小能手。
如果你是赤裸裸的編程新手,這篇教程也是為你準(zhǔn)備的!教程里貫穿有簡(jiǎn)短的鍛煉和挑戰(zhàn)來(lái)給你一些編程練習(xí),同時(shí)測(cè)試你的知識(shí)。
需要準(zhǔn)備什么
要看這篇教程,你需要準(zhǔn)備如下的東西:
- 一臺(tái)運(yùn)行OS X El Captian(10.11)的Mac,帶有最新發(fā)布的更新并且安裝了安全補(bǔ)丁。這樣你才能夠安裝需要的開(kāi)發(fā)工具:最新版本的Xcode。
- Xcode 7.3 或更新的版本。Xcode是用Swift寫(xiě)代碼的主要開(kāi)發(fā)工具。最小也需要Xcode 7.3版本,因?yàn)槟莻€(gè)版本包含Swift 2.2。你可以免費(fèi)從Mac App Store下載Xcode的最新版本,這里:http://apple.co/1FLn51R。
如果你還沒(méi)有安裝Xcode最新版本,在繼續(xù)看下面的教程前要確定安裝。
如何使用這篇教程
每篇教程都會(huì)介紹觸手可及的話題理論,伴隨大量Swift代碼來(lái)示范在學(xué)習(xí)的實(shí)際的應(yīng)用程序。
教程里的所有代碼都是平臺(tái)中立的;這意味著不是為iOS、OS X或任何其它平臺(tái)而特定。代碼在playgrounds里運(yùn)行,你在本篇中已經(jīng)學(xué)習(xí)了。
在剩下的教程里,你可以把代碼在自己的playground里輸入進(jìn)去。這樣你就可以和代碼“玩耍”(play around),做一些改變立即就能看見(jiàn)代碼運(yùn)行的結(jié)果。
剩下的教程里會(huì)貫穿實(shí)際小練習(xí),都是簡(jiǎn)短的練習(xí),關(guān)于觸手可及的主題。每篇的末尾也有挑戰(zhàn),會(huì)有編程問(wèn)題也會(huì)有長(zhǎng)一點(diǎn)的代碼練習(xí)來(lái)測(cè)試你的知識(shí)。做完就能掌握大部分的Swift基礎(chǔ)知識(shí)。