? ? 隨著蘋果swift的開(kāi)源,又開(kāi)啟了一段新的學(xué)習(xí)旅程,不過(guò)也是必然的,那現(xiàn)在開(kāi)始整理一下swift的筆記吧.
以下是一些swift學(xué)習(xí)資源的網(wǎng)址,現(xiàn)分享給大家!
* 蘋果官方博客 https://developer.apple.com/swift/blog/
* 開(kāi)源github https://github.com/apple/swift
* 蘋果官方 Swift 2.0 電子書 https://itunes.apple.com/us/book/id1002622538
* 2.0 中文版 http://wiki.jikexueyuan.com/project/swift/
* Let's Swift? http://letsswift.com/
* 100個(gè)Swift必備tips俏险,作者王巍畔濒,建議購(gòu)買實(shí)體書 http://onevcat.com
一.Swift和OC的簡(jiǎn)單對(duì)比
? ?1.在 Swift 中沒(méi)有了 main.m盏道,@UIApplicationMain 是程序入口
? ?2.在 Swift 中只有 .swift 文件胀茵,沒(méi)有 .h/.m 文件的區(qū)分
? ?3.在 Swift 中,一個(gè)類就是用一對(duì) {} 括起的胁后,沒(méi)有 @implementation 和 @end
? ?4.每個(gè)語(yǔ)句的末尾沒(méi)有分號(hào)硫眯,在其他語(yǔ)言中,分號(hào)是用來(lái)區(qū)分不同語(yǔ)句的
? ?5.在 Swift 中择同,一般都是一行一句代碼,因此不用使用分號(hào)
? ?6.與 OC 的語(yǔ)法快速對(duì)比
? ?7.在 OC 中 alloc / init 對(duì)應(yīng) ()
? ?8.在 OC 中 alloc / initWithXXX 對(duì)應(yīng) (XXX: )
? ?9.在 OC 中的類函數(shù)調(diào)用净宵,在 Swift 中敲才,直接使用 .
? ?10.在 Swift 中,絕大多數(shù)可以省略 self.择葡,建議一般不寫紧武,可以提高對(duì)語(yǔ)境的理解(閉包時(shí)會(huì)體會(huì)到)
? ?11.在 OC 中的 枚舉類型使用 UIButtonTypeContactAdd,而 Swift 中分開(kāi)了敏储,操作熱鍵:回車 -> 向右 -> .
? ?12.Swift 中阻星,枚舉類型的前綴可以省略,如:.ContactAdd已添,但是:很多時(shí)候沒(méi)有智能提示
? ?13.監(jiān)聽(tīng)方法妥箕,直接使用字符串引起
? ?14.在 Swift 中使用 print() 替代 OC 中的 NSLog
二.Swift的基本使用
2.1 常量和變量
?let 定義常量,一經(jīng)賦值不允許再修改
? ? ? ?var 定義變量更舞,賦值之后仍然可以修改
注意:1.應(yīng)該盡量先選擇常量畦幢,只有在必須修改時(shí),才需要修改為 var
? ? ? ?2.在 Xcode 7.0 中缆蝉,如果沒(méi)有修改變量宇葱,Xcode 會(huì)提示修改為 let
? ? ? Swift能夠根據(jù)右邊的代碼,推導(dǎo)出變量的準(zhǔn)確類型
? ? ? ?通常在開(kāi)發(fā)時(shí)刊头,不需要指定變量的類型
? ? ? ?如果要指定變量黍瞧,可以在變量名后使用:,然后跟上變量的類型
? ? ? ?wift 對(duì)數(shù)據(jù)類型要求異常嚴(yán)格
? ? ? ?任何時(shí)候原杂,都不會(huì)做隱式轉(zhuǎn)換
? ? ? ?如果要對(duì)不同類型的數(shù)據(jù)進(jìn)行計(jì)算印颤,必須要顯式的轉(zhuǎn)換
2.2 可選項(xiàng)Optional
? ? ? ?定義變量時(shí),如果指定是可選的穿肄,表示該變量可以有一個(gè)指定類型的值膀哲,也可以是 nil
? ? ? ?定義變量時(shí)往产,在類型后面添加一個(gè) ?,表示該變量是可選的
? ? ? ?變量可選項(xiàng)的默認(rèn)值是 nil
? ? ? ?常量可選項(xiàng)沒(méi)有默認(rèn)值某宪,主要用于在構(gòu)造函數(shù)中給常量設(shè)置初始數(shù)值
? ? ? ?如果 Optional 值是 nil仿村,不允許參與計(jì)算,只有解包(unwrap)后才能參與計(jì)算,在變量后添加一個(gè) !,可以強(qiáng)行解包
注意:必須要確保解包后的值不是 nil兴喂,否則會(huì)報(bào)錯(cuò)
? ? ? ??? 運(yùn)算符可以用于判斷 變量/常量 的數(shù)值是否是 nil蔼囊,如果是則使用后面的值替代
? ? ? ?在使用 Swift 開(kāi)發(fā)時(shí),?? 能夠簡(jiǎn)化代碼的編寫
2.3 控制流
if:Swift 中沒(méi)有 C 語(yǔ)言中的非零即真概念;在邏輯判斷時(shí)必須顯示地指明具體的判斷條件 true / false;if 語(yǔ)句條件的 () 可以省略,但是 {} 不能省略
三目:Swift 中的 三目 運(yùn)算保持了和 OC 一致的風(fēng)格
可選項(xiàng):由于可選項(xiàng)的內(nèi)容可能為 nil衣迷,而一旦為 nil 則不允許參與計(jì)算,因此在實(shí)際開(kāi)發(fā)中畏鼓,經(jīng)常需要判斷可選項(xiàng)的內(nèi)容是否為 nil
if let :不能與使用 &&、|| 等條件判斷,如果要增加條件壶谒,可以使用 where 子句,注意:where 子句沒(méi)有智能提示
guard:guard 是與 if let 相反的語(yǔ)法云矫,Swift 2.0 推出的.使用 guard 的好處:能夠判斷每一個(gè)值;在真正的代碼邏輯部分,省略了一層嵌套
switch:switch 不再局限于整數(shù);switch 可以針對(duì)任意數(shù)據(jù)類型進(jìn)行判斷;不再需要 break;每一個(gè) case后面必須有可以執(zhí)行的語(yǔ)句;要保證處理所有可能的情況汗菜,不然編譯器直接報(bào)錯(cuò)让禀,不處理的條件可以放在 default 分支中;每一個(gè) case 中定義的變量?jī)H在當(dāng)前 case 中有效,而 OC 中需要使用 {};switch 中同樣能夠賦值和使用 where 子句
2.4 循環(huán)
1,OC 風(fēng)格的循環(huán);2,for-in陨界,0..<10 表示從0到9;3,范圍 0...10 表示從0到10;4,省略下標(biāo)
_ 能夠匹配任意類型,_ 表示忽略對(duì)應(yīng)位置的值
for _ in 0...10 {print("hello")}表示打印10次hello
2.5 字符串
1.在 Swift 中絕大多數(shù)的情況下巡揍,推薦使用 String 類型
String和NSString的區(qū)別:String 是一個(gè)結(jié)構(gòu)體,性能更高;String 目前具有了絕大多數(shù);NSString 的功能;String 支持直接遍歷;NSString 是一個(gè) OC 對(duì)象菌瘪,性能略差;Swift 提供了 String 和 NSString 之間的無(wú)縫轉(zhuǎn)換
2.遍歷字符串中的字符
for s in str.characters {
print(s)
}
3.字符串長(zhǎng)度
// 返回以字節(jié)為單位的字符串長(zhǎng)度腮敌,一個(gè)中文占 3 個(gè)字節(jié)
let len1 = str.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)
// 返回實(shí)際字符的個(gè)數(shù)
let len2 = str.characters.count
// 返回 utf8 編碼長(zhǎng)度
let len3 = str.utf8.count
4.字符串拼接
直接在 "" 中使用 \(變量名) 的方式可以快速拼接字符串
let str1 = "Hello"
let str2 = "World"
let i = 32
str = "\(i) 個(gè) " + str1 + " " + str2
5.可選項(xiàng)的拼接
如果變量是可選項(xiàng),拼接的結(jié)果中會(huì)有 Optional,為了應(yīng)對(duì)強(qiáng)行解包存在的風(fēng)險(xiǎn)俏扩,蘋果提供了 ?? 操作符,?? 操作符用于檢測(cè)可選項(xiàng)是否為 nil,如果不是 nil糜工,使用當(dāng)前值,如果是 nil,使用后面的值替代
let str1 = "Hello"
let str2 = "World"
let i: Int? = 32
str = "\(i ?? 0) 個(gè) " + str1 + " " + str2
6.格式化字符串
在實(shí)際開(kāi)發(fā)中录淡,如果需要指定字符串格式啤斗,可以使用 String(format:...) 的方式
let h = 8
let m = 23
let s = 9
let timeString = String(format: "%02d:%02d:%02d", arguments: [h, m, s])
let timeStr = String(format: "%02d:%02d:%02d", h, m, s)
7.String & Range 的結(jié)合
在 Swift 中,String 和 Range連用時(shí)赁咙,語(yǔ)法結(jié)構(gòu)比較復(fù)雜,如果不習(xí)慣 Swift 的語(yǔ)法钮莲,可以將字符串轉(zhuǎn)換成 NSString 再處理
let helloString = "我們一起飛"
(helloString as NSString).substringWithRange(NSMakeRange(2, 3))
使用 Range 的寫法
let startIndex = helloString.startIndex
let endIndex = helloString.endIndex
helloString.substringWithRange(startIndex..
2.6 集合
1.數(shù)組
數(shù)組使用 [] 定義,這一點(diǎn)與 OC 相同
//: [Int]
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
遍歷
for num in numbers {
print(num)
}
通過(guò)下標(biāo)獲取指定項(xiàng)內(nèi)容
let num1 = numbers[0]
let num2 = numbers[1]
可變&不可變
let 定義不可變數(shù)組
var 定義可變數(shù)組
let array = ["zhangsan", "lisi"]
//: 不能向不可變數(shù)組中追加內(nèi)容
//array.append("wangwu")
var array1 = ["zhangsan", "lisi"]
//: 向可變數(shù)組中追加內(nèi)容
array1.append("wangwu")
數(shù)組的類型
如果初始化時(shí)彼水,所有內(nèi)容類型一致崔拥,擇數(shù)組中保存的是該類型的內(nèi)容
如果初始化時(shí),所有內(nèi)容類型不一致凤覆,擇數(shù)組中保存的是 NSObject
//: array1 僅允許追加 String 類型的值
//array1.append(18)
var array2 = ["zhangsan", 18]
//: 在 Swift 中链瓦,數(shù)字可以直接添加到集合,不需要再轉(zhuǎn)換成 `NSNumber`
array2.append(100)
//: 在 Swift 中,如果將結(jié)構(gòu)體對(duì)象添加到集合慈俯,仍然需要轉(zhuǎn)換成 `NSValue`
array2.append(NSValue(CGPoint: CGPoint(x: 10, y: 10)))
數(shù)組的定義和實(shí)例化
使用 : 可以只定義數(shù)組的類型
實(shí)例化之前不允許添加值
使用 [類型]() 可以實(shí)例化一個(gè)空的數(shù)組
var array3: [String]
//: 實(shí)例化之前不允許添加值
//array3.append("laowang")
//: 實(shí)例化一個(gè)空的數(shù)組
array3 = [String]()
array3.append("laowang")
數(shù)組的合并
必須是相同類型的數(shù)組才能夠合并
開(kāi)發(fā)中渤刃,通常數(shù)組中保存的對(duì)象類型都是一樣的!
array3 += array1
//: 必須是相同類型的數(shù)組才能夠合并贴膘,以下兩句代碼都是不允許的
//array3 += array2
//array2 += array3
數(shù)組的刪除
//: 刪除指定位置的元素
array3.removeAtIndex(3)
//: 清空數(shù)組
array3.removeAll()
內(nèi)存分配
如果向數(shù)組中追加元素卖子,超過(guò)了容量,會(huì)直接在現(xiàn)有容量基礎(chǔ)上 * 2
var list = [Int]()
for i in 0...16 {
list.append(i)
print("添加 \(i) 容量 \(list.capacity)")
}
2字典
同樣使用 [] 定義字典,let 不可變字典,var 可變字典,[String : NSObject] 是最常用的字典類型
var dict = ["name": "zhangsan", "age": 18]
賦值直接使用 dict[key] = value 格式,如果 key 不存在刑峡,會(huì)設(shè)置新值,如果 key 存在洋闽,會(huì)覆蓋現(xiàn)有值
//: * 如果 key 不存在,會(huì)設(shè)置新值
dict["title"] = "boss"
//: * 如果 key 存在突梦,會(huì)覆蓋現(xiàn)有值
dict["name"] = "lisi"
dict遍歷:k诫舅,v 可以隨便寫,前面的是 key,后面的是 value
for (k, v) in dict {
print("\(k) ~~~ \(v)")
}
合并字典
如果 key 不存在,會(huì)建立新值宫患,否則會(huì)覆蓋現(xiàn)有值
//: 合并字典
var dict1 = [String: NSObject]()
dict1["nickname"] = "大老虎"
dict1["age"] = 100
//: 如果 key 不存在刊懈,會(huì)建立新值,否則會(huì)覆蓋現(xiàn)有值
for (k, v) in dict1 {
dict[k] = v
}
print(dict)
三.函數(shù)
3.1函數(shù)
函數(shù)的定義:格式 func 函數(shù)名(行參列表) -> 返回值 {代碼實(shí)現(xiàn)};調(diào)用 let result = 函數(shù)名(值1, 參數(shù)2: 值2...)
沒(méi)有返回值的函數(shù)娃闲,一共有三種寫法:省略,(),Void
外部參數(shù):在形參名前再增加一個(gè)外部參數(shù)名虚汛,能夠方便調(diào)用人員更好地理解函數(shù)的語(yǔ)義;格式:func 函數(shù)名(外部參數(shù)名 形式參數(shù)名: 形式參數(shù)類型) -> 返回值類型 { // 代碼實(shí)現(xiàn) };Swift 2.0 中,默認(rèn)第一個(gè)參數(shù)名省略
3.2閉包
定義:定義一個(gè)函數(shù)
//: 定義一個(gè) sum 函數(shù)
func sum(num1 num1: Int, num2: Int) -> Int {
return num1 + num2
}
sum(num1: 10, num2: 30)
//: 在 Swift 中函數(shù)本身就可以當(dāng)作參數(shù)被定義和傳遞
let mySum = sum
let result = mySum(num1: 20, num2: 30)
定義一個(gè)閉包
閉包 = { (行參) -> 返回值 in // 代碼實(shí)現(xiàn) }
in 用于區(qū)分函數(shù)定義和代碼實(shí)現(xiàn)
//: 閉包 = { (行參) -> 返回值 in // 代碼實(shí)現(xiàn) }
let sumFunc = { (num1 x: Int, num2 y: Int) -> Int in
return x + y
}
sumFunc(num1: 10, num2: 20)
最簡(jiǎn)單的閉包畜吊,如果沒(méi)有參數(shù)/返回值,則 參數(shù)/返回值/in 統(tǒng)統(tǒng)都可以省略
{ 代碼實(shí)現(xiàn) }
let demoFunc = {
print("hello")
}
基本使用
GCD 異步
模擬在后臺(tái)線程加載數(shù)據(jù)
func loadData() {
dispatch_async(dispatch_get_global_queue(0, 0), { () -> Void in
print("耗時(shí)操作 \(NSThread .currentThread())")
})
}
尾隨閉包户矢,如果閉包是最后一個(gè)參數(shù)玲献,可以用以下寫法
注意上下兩段代碼,} 的位置
func loadData() {
dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
print("耗時(shí)操作 \(NSThread .currentThread())")
}}
閉包的簡(jiǎn)寫梯浪,如果閉包中沒(méi)有參數(shù)和返回值捌年,可以省略
func loadData() {
dispatch_async(dispatch_get_global_queue(0, 0)) {
print("耗時(shí)操作 \(NSThread .currentThread())")
}}
自定義閉包參數(shù),實(shí)現(xiàn)主線程回調(diào)
添加沒(méi)有參數(shù)挂洛,沒(méi)有返回值的閉包
override func viewDidLoad() {
super.viewDidLoad()
loadData {
print("完成回調(diào)")
}
}
// MARK: - 自定義閉包參數(shù)
func loadData(finished: ()->()) {
dispatch_async(dispatch_get_global_queue(0, 0)) {
print("耗時(shí)操作 \(NSThread.currentThread())")
dispatch_sync(dispatch_get_main_queue()) {
print("主線程回調(diào) \(NSThread.currentThread())")
// 執(zhí)行回調(diào)
finished()
}}}
添加回調(diào)參數(shù)
override func viewDidLoad() {? ?
?super.viewDidLoad()? ?
?loadData4 { (html) -> () in? ? ? ?
?print(html)? ? }}
/// 加載數(shù)據(jù)/// 完成回調(diào) - 傳入回調(diào)閉包礼预,接收異步執(zhí)行的結(jié)果func loadData4(finished: (html: String) -> ()) {? ? dispatch_async(dispatch_get_global_queue(0, 0)) {? ? ?
?? print("加載數(shù)據(jù) \(NSThread.currentThread())")? ? ? ? dispatch_sync(dispatch_get_main_queue()) {? ? ? ? ? ?
?print("完成回調(diào) \(NSThread.currentThread())")? ? ? ? ??
? finished(html: "
hello world
")? ? ? ? }? ? }}
閉包(Block) 的循環(huán)引用小結(jié)
Swift
[weak self]
self是可選項(xiàng),如果self已經(jīng)被釋放虏劲,則為nil
[unowned self]
self不是可選項(xiàng)托酸,如果self已經(jīng)被釋放,則出現(xiàn)野指針訪問(wèn)
Objc
__weak typeof(self) weakSelf;
如果self已經(jīng)被釋放柒巫,則為nil
__unsafe_unretained typeof(self) weakSelf;
如果self已經(jīng)被釋放励堡,則出現(xiàn)野指針訪問(wèn)