WWDC14 Session 402 學習筆記 (上)

前言

這篇是Swift 系列教程的第一篇,即使是最簡單的第一篇也讓我這個三年多開發經驗的老菜鳥研究了一下午才寫出來這篇文章的。

Swift這個語言各個方面的東西都不齊全,語法上,文檔上,社區上。所以毫無iOS經驗或者iOS初學者,我強烈不建議現在就學習這門語言。

這裡舉個非常非常坑的例子:

1
2
3
4
5
6
7
8
9
import Cocoa

var a = [1, 2, 3]
var b = a[0...2]
var c = a

a===b
b===c
c===a

這個東西吧,第一句話是否註釋掉結果截然不同。我們日常討論的問題好多都是去掉了Cocoa 之後是另外一個樣子。可見蘋果對於這門語言的設計還是不夠規範的。故我不推薦新手們浪費時間去學這個東西,以及Swift 就目前來玩是完全無法替代Objective-C的,我們的項目基本上都會或多或少的混入一些C++的內容,例如自己的移動端通用的網絡協議、Facebook Pop、OpenCV之類。Swift是無法直接調用C++的,它需要用OC封裝好了去調用OC。

在我們開始寫正文之前,再啰嗦一句:

注意:這篇文章僅僅是WWDC Session 402 Introduction to Swift的學習筆記,不含任何意淫與揣測。所有代碼都是默認有import Cocoa的 : ]

Swift Basic

蘋果從WWDC Keynote 開場到 這個Session 都一直在提三個詞。SAFE/MODERN/POWER,包括Session上面講解每個feature的時候,都會說這個體現了Swift哪個特性,例如類型推斷 就體現了 SAFE 和 Modern 之類的。經常點題很棒,給好評!

衆所周知:程序 = 代碼 + 算法 + 數據結構,而代碼的基礎是組成每一句的變(常)量。

不過在我們在介紹常量之前,先高呼一聲:

1
println("Hello World!")

變(常)量

Swift 的 變量定義十分簡單:

1
var lang: String = "Swift"

我們前面說過Swift是內置類型推斷的,所以我們往往可以省略 :String

1
var lang = "Swift"

這裡有一個和Objective﹣C以及和Swift長得非常像的js之類的語言不同的地方,Swift的變量一旦聲明了,就不能修改類型了,上面的例子中lang只能是字符串類型。之後無論如何賦值都不能修改其類型。

所以我們說設置類型是往往可以省略的,但有些地方還是不能省略的。特別是在Collection類型上面,例如一個本來想放NSObject的字典,因為初始化用的字符串,就被推斷成了一個完全都是字符串的字典。

還有另外一個比較無厘頭的和Objective-C不同的地方,Swift 可以用任意Unicode字符當做變量名,也就是說,中文,表情符號,都是可以的。

1
2
var 🐱  "cat"
var 鼠標 = "🐭"

常量的定義和變量非常相似,將var換成let即可。非常有 Apple Script 范兒,是不是!

字符串

聲明

字符串的聲明我們上面提過了..

注意這裡生成的String,並不是NSString。他甚至都不是一個Object,我們可以在def裡面看到:

1
2
3
struct String {
    init()
}

String和CFString一樣,他是一個Struct! 不過,蘋果爸爸非常漂亮的給我們提供了便利的解決方案。String可以和NSString互相替代,而且API通用。

例如:

1
2
3
let components = ["~/txx/swift"]

OutPut: [~,"txx","swift"]

注意:result中的那個數組,並非是NSArray,而是Array。以及Array和String一樣,也是結構體。不過,Array不具有NSArray的API特性。需要顯示轉換成NSArray才可以調用其方法,這些我們之後再提。

枚舉

在Swift中,我們可以通過 for in 枚舉字符

1
2
3
4
5
let str = "swift"

for k in str{
    println(k)
}

這裡有個優化,與我們在OC下,用

1
- (unichar)characterAtIndex:(NSUInteger)index

枚舉的Char不同,這個是支持 Unicode 的, 也就是中文再也不會被拆成兩個字符了。

順路一說:我們可以通過

1
let dog: Character = "🐶"

生成一個純字符類型。

符號操作

加法:終於擺脫了OC那冗長的擴展 stringByAppendingFormat, 可以直接用++=代替了。

轉義:也擺脫了OC的stringFromFormat和 c style的 %d %@傳值。

1
2
let a = 3, b = 5
let ab = "\(a) * \(b) is \(a*b)"

Array

聲明

1
let a = ["a", "b", "c"]

不過這裡有點小坑,之後會說

枚舉

通過循環枚舉,即

1
2
3
4
5
6
7
while flag {enum(arr)}

for a in arr {}

for var i=1;i<13;++i {}

for i in 1..10 {}

這裡提一個細節:

  • .. 代表的是半開半閉區間也就是a..b就是[a,b)
  • ...代表一個完全封閉區間也就是a...b就是[a,b]

修改

  1. += 操作
1
2
3
var a = ["a"]
a += "b"
a += ["c", "d", "e"]

2. = 操作

1
2
a[0] = f
a[3..5] = ["c", "e"]

第一個操作很容易理解,第二個操作有點變態。因為他不是在 3..5 換成 [“c”, “e”]數組,如果我寫成了

1
a[3..3] = ["c", "e"]

你會發現他變成了插入,我猜這地方以後一定要出面試題!

我們可以這麼理解這句話,他幹的事情是:

  1. 把這個區間清空
  2. 在區間開始的位置,插入賦值的數組。

這個功能僅在區間狀態有效,如果a[3] = [“c”, “e”] 則會報錯

NS容器和Swift容器的區別

除了我之前提過的:雖說Array和String相仿,是一個 Struct,NSArray是一個Class,但Array的API與NSArray不能通用,不過可以像C#那樣通過as語法顯示轉換。但這裡面有點坑,這個Session也沒有說,我們就不提了。

還有兩點不同:

  1. Swift的Collection可以放入任何東西,即不只是Object,我還可以放入int\double這些類型。而NS系列必須是NSObject的子類
  2. Swift的Collection 是 Typed Collections,也就是我們上面說過的類型推斷。

如果我們用上面的代碼聲明了一個數組:

1
let a = ["a", "b", "c"]

那麼,a就是一個完全的字符串數組了,不可能再放入其他類型,而NSMutableArray的話,可以放入其他Object。

這裡稍微引申一下:

1
2
3
let a = ["a", 1]
let a: Array = ["a", 1]
let a: Array<any> = ["a", 1]

這三種情況,看起來可能 前兩種和第三種不同,但實際上是完全不同

  • 第一個被推斷為了 NSArray,之後不准做增加操作,會提示沒有重載 +=運算符
  • 第二個被推斷為了 NSObject[]
  • 第三個被推斷為了 Array

然後還發現了一個Bug

1
2
var a = ["a", "b", 1]
a += 1

貌似是 a 變成了 NSString,b還是String。

字典

聲明

1
var animalLegs = [pig: 4, "dog":4, "Snake":0]

枚舉

除了常規枚舉key去找value以外,Swift還支持枚舉元組(tuple)

1
2
3
4
5
var animalLegs = [pig: 4, "dog":4, "Snake":0]
for (animalName, Legs) in animalLegs
{
 blablabla
}

修改

1
2
3
var animalLegs = [pig: 4, "dog":4, "Snake":0]
animalLegs["chihuahua"] = 5  //Add new Key/Value
animalLegs["chihuahua"] = 4  //Modify Value

若不存在怎麼辦?我們明天再說~

Comments