Swift介紹
1.Swift由來(lái):
2010 年 7 月,蘋果 開發(fā)者工具部門總監(jiān) Chris Lattner 開始著手 Swift 編程語(yǔ)言的設(shè)計(jì)工作(用一年時(shí)間,完成基本架構(gòu))
Swift 語(yǔ)言由蘋果公司在 2014 年推出,用來(lái)撰寫 OS X 和 iOS 應(yīng)用程序,2016年9月, 正式發(fā)布了Swift3.0 (上一個(gè)版本是2.2,沒有固化API)
2.Swift 和 C/OC之間的關(guān)系?
Swift 結(jié)合了 C 和 Objective-C 的優(yōu)點(diǎn)并且不受 C 兼容性的限制。Swift 采用安全的編程模式并添加了很多新特性。
3.Swift特點(diǎn):
①?gòu)乃恼Z(yǔ)法中能看到Objective-C、JavaScript、C#、Python等語(yǔ)言的影子
②語(yǔ)法簡(jiǎn)單、代碼簡(jiǎn)潔、使用方便, 類型安全
③可與Objective-C混合使用(相互調(diào)用)
④提供了類似 Java 的命名空間(namespace)、泛型(generic)、運(yùn)算符重載(operator overloading)
總結(jié): 功能大, 性能高, 使用簡(jiǎn)潔, 代碼安全
4.Swift的重要性:
①?gòu)腟wift的幾個(gè)重大版本迭代, 蘋果目前在大力推廣Swift
②斯坦福大學(xué)的公開課目前也是使用Swift在授課.因?yàn)橐院骃wift確實(shí)是往后發(fā)展的趨勢(shì)
③現(xiàn)在很多公司, 已經(jīng)開始使用Swift進(jìn)行重構(gòu)項(xiàng)目
注意:目前而言, 市場(chǎng)上開發(fā)APP, 依舊是以O(shè)C為主; 所以O(shè)C也不能扔;Swift 它采用了 Objective-C 的命名參數(shù)以及動(dòng)態(tài)對(duì)象模型,可以無(wú)縫對(duì)接到現(xiàn)有的 Cocoa 框架,并且可以兼容 Objective-C 代碼。
5.Swift可以做哪些事情:
①iOS App
②Mac App
③服務(wù)器端
④安卓端
Swift語(yǔ)法
須知:
關(guān)于分號(hào),swift中, 一行語(yǔ)句結(jié)束, 可以不加分號(hào),添加的話, 也不會(huì)報(bào)錯(cuò),但是如果一行有多條語(yǔ)句, 還是需要使用分號(hào)進(jìn)行分割。
1.常量&變量
1)定義格式 (注意: [] 內(nèi)代表可以省略)
let 常量名稱 [:常量類型] = 值
var 變量名稱 [:變量類型] = 值
2)注意事項(xiàng):
- 必須指明是常量還是變量:常量: let 變量: var
- 變量名稱 可以是漢字, 或者Unicode字符
- 可以省略類型,swift中有個(gè)類型推導(dǎo)機(jī)制, 會(huì)自動(dòng)根據(jù)值來(lái)判斷是什么類型(常用option鍵 查看 變量或常量的類型)
- 值必須和類型相匹配, 否則報(bào)錯(cuò)
- Swift是類型安全的語(yǔ)言, 必須是相同類型的參數(shù), 才能進(jìn)行運(yùn)算
3) 開發(fā)選擇:
建議優(yōu)先選擇常量, 如果需要修改, 選擇變量
2.基本數(shù)據(jù)類型&類型轉(zhuǎn)換&類型推導(dǎo)
注意:Swift中的數(shù)據(jù)類型也有:整型/浮點(diǎn)型/對(duì)象類型/結(jié)構(gòu)體類型等等
1)整形
OC:
有符號(hào): signed 例如: NSInteger (跟平臺(tái), CPU相關(guān))
無(wú)符號(hào):unsigned 例如:NSUInteger (跟平臺(tái), CPU相關(guān))
Swift:
有符號(hào): 例如:Int : 和平臺(tái)相關(guān)(默認(rèn),相當(dāng)于OC的NSInteger)
無(wú)符號(hào): 例如:UInt : 和平臺(tái)相關(guān)(常用,相當(dāng)于OC的NSUInteger)(默認(rèn))
2)浮點(diǎn)型
OC與Swift均包含:float 和 double
3)布爾類型
OC:
C語(yǔ)言和OC并沒有真正的Bool類型,C語(yǔ)言的Bool類型非0即真,
OC語(yǔ)言的Bool類型是:
①定義一個(gè)布爾類型 typedef signed char BOOL;
②條件判斷中:OC中if條件可以是任何 整數(shù)(非0即真)
存在的問題是:可能將判斷寫錯(cuò), 寫成了賦值 if(isOpen = 2) ,
在開發(fā)中為了避免這個(gè)問題有經(jīng)驗(yàn)的程序員會(huì)這樣寫 if(2 == isOpen)來(lái)避免這個(gè)問題.
Swift:
引入了真正的Bool類型:true/false
Swift中if的條件只能是一個(gè)Bool的值或者是返回值是Bool類型的表達(dá)式(==/!=/>/<等等)
注意事項(xiàng):
由于Swift是類型安全的語(yǔ)言:
①Swift必須明確數(shù)據(jù)類型(1. 直接指明數(shù)據(jù)類型 2. "類型推導(dǎo)機(jī)制"自動(dòng)推導(dǎo))
②如果取值錯(cuò)誤會(huì)直接報(bào)錯(cuò), 而OC不會(huì)
③Swift會(huì)進(jìn)行溢出檢查, 而OC不會(huì)
④Swift沒有隱式類型轉(zhuǎn)換, 不允許不同類型的數(shù)據(jù)類型進(jìn)行運(yùn)算(需要進(jìn)行強(qiáng)制轉(zhuǎn)換)
3.Swift基本運(yùn)算:
OC: 有隱式轉(zhuǎn)換, 所以允許不同類型的數(shù)據(jù)進(jìn)行運(yùn)算
Swift: 沒有隱式轉(zhuǎn)換, 必須指明類型后才能運(yùn)算!!
1)算術(shù)運(yùn)算符: + - * / % (注意在swift3.0中, ++ --運(yùn)算已經(jīng)被取消 使用 += , -=代替)
2)關(guān)系運(yùn)算符: > < >= <= == !=
3)賦值運(yùn)算: = += -= /= *= %=
4)邏輯運(yùn)算符: ! && || ( 基本用法和OC一樣)
注意:① Swift中的邏輯運(yùn)算符只能操作Bool類型數(shù)據(jù), 而OC可以操作整形(非0即真)
②溢出檢查(會(huì)對(duì)顯式/隱式的數(shù)值進(jìn)行編譯檢查)
4.邏輯分支(if else if的使用)
- OC:
①if 后面條件必須加()
②if 后面條件, 非0即真 (容易引發(fā)一些沒有必要的問題)
③如果只有一條指令if后面的大括號(hào)可以省略 - Swift:
①if 后面條件不加()
②if 后面條件, 必須是明確的Bool類型
③即使只有一條指令if后面的大括號(hào)不可以省略
④if else if的使用:類似OC
⑤三目運(yùn)算符:OC和Swift基本一致
5.邏輯分支(guard的使用)
Swift特有的:
①guard是Swift2.0新增的語(yǔ)法,它與if語(yǔ)句非常類似,它設(shè)計(jì)的目的是提高程序的可讀性
②guard 必須使用在函數(shù)里面
③guard語(yǔ)句必須帶有else語(yǔ)句,它的語(yǔ)法如下:
當(dāng)條件表達(dá)式為true時(shí)候跳過else語(yǔ)句中的內(nèi)容,執(zhí)行語(yǔ)句組內(nèi)容
條件表達(dá)式為false時(shí)候執(zhí)行else語(yǔ)句中的內(nèi)容
(跳轉(zhuǎn)語(yǔ)句一般是return、break、continue和throw)
6.邏輯分支(switch的基本使用)
- OC:
①switch 后面條件必須加 ( )
②case后面只能跟一個(gè)條件
③case會(huì)有穿透效果
④可以不寫default,default位置可以隨便放
⑤在case中定義變量需要加大括號(hào), 否則作用域混亂
⑥不能判斷對(duì)象或者浮點(diǎn)類型, 只能判斷整數(shù) - Swift:
與OC以上條件完全相反
注意:如果想要穿透效果 需要在case 之后使用 fallthrough,默認(rèn)一個(gè)fallthrough只會(huì)穿透一層
7.邏輯分支(switch的特殊用法)
Swift新特性:
①區(qū)間匹配 比如: case 0…9:
②元組匹配 比如: case (0…10,10…20): 或者 case(_ , 0):等等
③值綁定 比如: case(var x,10): //x有外界傳值進(jìn)來(lái)
④根據(jù)條件綁定 比如: case var(x, y) where x > y: //只有滿足條件才會(huì)執(zhí)行
區(qū)間概念解釋:通常描述的是數(shù)字區(qū)間
①半開半閉區(qū)間 例如: 0到100(不包括100) => 0..<100
②閉區(qū)間 例如: 0到100(包括100) => 0…100
swift3.0: 可以包含小數(shù) 例如:let qujian = 0.1...9.9
8.for循環(huán)的使用
傳統(tǒng)寫法:
for var i = 0; i < 10; i ++ { }
區(qū)間寫法:
for i in 0..<10 { }
或者
for _ in 0..<10 { }
9.while&dowhile循環(huán)
總結(jié):
①while 后面的 () 可以省略
②后面的條件沒有'非0即真’只能是True或false
③使用repeat關(guān)鍵字來(lái)代替了do
例如:
1.while循環(huán)
var a = 10
while a > 0 { print(a) }
2.do-while循環(huán)
var m = 10
repeat { m -= 1
print(m)
}while(m > 0)
10.字符串的基本使用
1)OC和Swift中字符串的區(qū)別:
① 在OC中字符串類型時(shí)NSString,在Swift中字符串類型是String
② OC中字符串@"",Swift中字符串""
2)使用 `String` 的原因:
①`String` 是一個(gè)結(jié)構(gòu)體,性能更高,而`NSString` 是一個(gè) `OC` 對(duì)象,性能略差
②`String` 支持直接遍歷
3)字符串的定義:
定義不可變字符串 和定義可變字符串
4)字符串的使用:
①獲取字符串的長(zhǎng)度
②遍歷字符串
③字符串拼接 (字符串和字符串的拼接,字符串和其他數(shù)據(jù)類型的拼接)
④字符串的格式化 (比如輸出時(shí)間:03:04)
11.字符串的截取
<1> Swift中提供了特殊的截取方式 :
1)從開始位置截取
let startIndex = url.startIndex
url.substring(from: startIndex)
2)截取至結(jié)束位置
let endIndex = url.index(startIndex,offsetBy: 7)
url.substring(to: endIndex)
3)截取中間的字符串
let range = Range(start: str.startIndex.advancedBy(4),end:str.endIndex.advancedBy(-4))
let middle = str.substringWithRange(range)
<2> 字符串替換:
str.replaceSubrange(str.startIndex...str.index(str.startIndex, offsetBy: 2),with: "1234")
<3>簡(jiǎn)單的方式是將String轉(zhuǎn)成NSString來(lái)使用:
`Swift` 提供了 `String` 和 `NSString` 之間的無(wú)縫轉(zhuǎn)換 ,在標(biāo)識(shí)符后加as NSString即可
12.數(shù)組
1.數(shù)組的基本使用:
數(shù)組的定義:
不可變數(shù)組 let
可變數(shù)組 var
數(shù)組元素的基本操作: 增刪改查
2.數(shù)組的其他操作:
①求個(gè)數(shù)
個(gè)數(shù) :count
容量:capacity 一般都是2的倍數(shù)(特例: 剛初始化時(shí), 容量大小, 和真實(shí)的容量大小一致)
例如:var array = [1, 2, 3]
array.capacity == array.count // 3
②數(shù)組遍歷
1)一般場(chǎng)景遍歷:
for i in 0..<array.count (Swift3.0過期)
2)forin方式:
for item in array
3)設(shè)置遍歷的區(qū)間:
for item in array[0..<2]
4)遍歷數(shù)組的同時(shí)獲取下標(biāo)值
for (index, name) in names.enumerate()
③數(shù)組合并
注意:只有相同類型的數(shù)組才能合并 ([Any]則什么都可以保存)
不建議一個(gè)數(shù)組中存放多種類型的數(shù)據(jù)
13.字典的使用
1.字典的概念:
字典是由兩部分集合構(gòu)成的,一個(gè)是鍵(key)集合,一個(gè)是值(value)集合
注意:
①字典允許按照某個(gè)鍵來(lái)訪問元素
②鍵集合是不能有重復(fù)元素的,而值集合是可以重復(fù)的,鍵和值是成對(duì)出現(xiàn)的
③Swift字典類型是Dictionary,也是一個(gè)泛型集合
2.字典的初始化:
須知: Swift中的可變和不可變字典( let修飾不可變字典,var修飾可變字典)
聲明一個(gè)Dictionary類型的時(shí)候可以使用下面的語(yǔ)句之一(或者利用自動(dòng)推倒字典類型):
var dict1:Dictionary<Int, String>
var dict2:[Int: String]
注意:swift中任意值,通常不使用NSObject,使用Any
=> var dict:Dictionary<String, Any>
3.字典元素的基本操作
①增
dic[key] = value 或者 updateValue
注意: 兩種方式幾乎一致: 一旦發(fā)現(xiàn)沒有找到對(duì)應(yīng)的key, 都會(huì)新增一個(gè)鍵值對(duì)
②刪
removeValueForKey 或者 removeAll
③改
dic[key] = value 或者 updateValue
④查
dic[key]
4.字典的基本操作
字典的遍歷:
遍歷字典中所有的值
遍歷字典中所有的鍵
遍歷所有的鍵值對(duì)
字典的合并:
字典不可以直接相加合并
=> 合并方案:
for (key, value) in dict1 {
dict2[key] = value
}
14.元組的使用
1.元組的介紹
須知:元組是Swift中特有的,OC中并沒有相關(guān)類型
①它是一種數(shù)據(jù)結(jié)構(gòu),在數(shù)學(xué)中應(yīng)用廣泛
②類似于數(shù)組或者字典,可以用于定義一組數(shù)據(jù),組成元組類型的數(shù)據(jù)可以稱為“元素”
例如:使用元組描述一個(gè)人的信息 => ("1001", "張三", 30, 90.1)
2.元組的簡(jiǎn)單使用:
1)數(shù)組寫法: let array = [404, "Not Found"]
2)元組寫法:
方式一:
let error = (404, "NotFound")
print(error.0)
print(error.1)
方式二:
let error = (errorCode: 404,errorInfo: "Not Found")
print(error.errorCode)
print(error.errorInfo)
方式三:
let (errorCode,errorIno) = (404, "Not Found")
print(errorCode)
print(errorIno)
3)元組的應(yīng)用場(chǎng)景: 參數(shù) / 返回值
15.可選類型的使用
1.可選類型的定義: 一個(gè)變量, 要么有值, 要么沒有值
2.可選類型產(chǎn)生的原因:
比如: OC中, 基本數(shù)據(jù)類型, 如果不賦值, 都會(huì)存在默認(rèn)值; 所以不會(huì)產(chǎn)生"沒有值的情況”
但是: 沒有值和有默認(rèn)值, 是完全不同的兩個(gè)概念
所以在Swift中引入了"可選類型的概念”: 區(qū)分了"有值" 和 "沒有值" 的兩種狀態(tài)
3. 定義可選類型
最基本的寫法: let name : Optional<String> = nil
語(yǔ)法糖(常用): let name : String? = nil
4. 可選類型的使用
var string : Optional<String> = nil
string = "Hello world” //可選類型賦值
print(string!)
注意:
如果可選類型為nil,強(qiáng)制取出其中的值(解包),會(huì)出錯(cuò)
正確寫法如下:
方式一:
for string != nil{
print(string!)
}
方式二:可選綁定
if let str = string {
print(str)
}
方式三:guard守護(hù)
func test(optionSte: option?){
guard let str = string else{
return
}
print(str)
}
5.真實(shí)應(yīng)用場(chǎng)景:
1. 把字符串轉(zhuǎn)成int類型
2. 根據(jù)字符串創(chuàng)建NSURL對(duì)象
NSURL(string: "www.520it.com”)
3. 圖片的創(chuàng)建
4. 函數(shù)的處理
16.類型轉(zhuǎn)換
常見的類型轉(zhuǎn)化符號(hào):
is : 用于判斷一個(gè)實(shí)例是否是某一種類型
as : 將實(shí)例轉(zhuǎn)成某一種類型 (比如子類->父類轉(zhuǎn)換)
as? 將某個(gè)類型轉(zhuǎn)成可選類型,通過判斷可選類型是否有值,來(lái)決定是否轉(zhuǎn)化成功了
as! 將某個(gè)類型轉(zhuǎn)成具體的類型,但是注意:如果不是該類型,那么程序會(huì)崩潰
17.空合運(yùn)算符
用法: 可選類型的變量 ?? "為空時(shí)的代替值” (類似于使用三目運(yùn)算符判斷一個(gè)變量是否為空)
意思: 如果可選類型的變量值為nil, 則使用設(shè)置的代替值, 如果有值, 直接解包使用
18.函數(shù)的基本使用
1)函數(shù)的介紹 : 函數(shù)相當(dāng)于OC中的方法
2)swift 函數(shù)的格式: func 函數(shù)名(參數(shù)列表) -> 返回值類型 { 代碼塊 return 返回值 }
注意: ①func是關(guān)鍵字,多個(gè)參數(shù)列表之間可以用逗號(hào)(,)分隔,也可以沒有參數(shù)
②使用箭頭“->”指向返回值類型
③如果函數(shù)沒有返回值,返回值為Void. 并且“-> 返回值類型”部分可以省略
3)常見函數(shù)類型:
①無(wú)參數(shù)無(wú)返回值
func about() -> Void { print("iphone6s plus") }
簡(jiǎn)便寫法:如果沒用返回值,Void可以寫成() 或者返回值直接不寫
=> func about() { print("iphone6s plus") }
②有參數(shù)無(wú)返回值
func callPhone(phoneNum : String) { print("打電話給\(phoneNum)") }
③無(wú)參數(shù)有返回值
func readMessage() -> String { return "吃飯了嗎?" }
④有參有返回值
func sum(num1 : Int, num2 : Int) -> Int { return num1 + num2 }
特例: 有多個(gè)返回值的函數(shù)(返回元組)
=> func getPerson() -> (name: String, age: Int) { return ("sz", 18) }
19.函數(shù)的使用注意:
1)外部參數(shù)和內(nèi)部參數(shù):
概念:在函數(shù)內(nèi)部可以看到的參數(shù),就是內(nèi)部參數(shù), 在函數(shù)外面可以看到的參數(shù),就是外部參數(shù)
自swift3.0開始,如果你沒有提供外部參數(shù),則參數(shù)名稱既是內(nèi)部參數(shù)也是外部參數(shù)
(如果不想要外部參數(shù),可以在參數(shù)名稱前加_)
2)默認(rèn)參數(shù):
某些情況,如果沒有傳入具體的參數(shù),可以使用默認(rèn)參數(shù) 例如:test6(19) test6(b: 88)
注意: 如果使用默認(rèn)值, 那么函數(shù)的接收參數(shù)可以是必傳參數(shù)和可傳參數(shù)的任意組合
3)可變參數(shù)
swift中函數(shù)的參數(shù)個(gè)數(shù)可以變化,它可以接受不確定數(shù)量的輸入類型參數(shù)
我們可以通過在參數(shù)類型名后面加入(...)的方式來(lái)指示這是可變參數(shù)
注意:①它們必須具有相同的類型
② 可變參數(shù), 就是外界直接傳遞過來(lái)多個(gè)參數(shù)
③ 函數(shù)內(nèi)部, 是把這些參數(shù)當(dāng)做一個(gè)數(shù)組來(lái)進(jìn)行處理
4)經(jīng)驗(yàn)總結(jié):
①在函數(shù)內(nèi)部, 默認(rèn)接收到的參數(shù)被賦值給一個(gè)常量, 故不允許改變。
在swift3.0中, 如果想要改變,需要在函數(shù)內(nèi)部, 使用var 間接改變 (不建議這樣干)
② 默認(rèn)情況下,函數(shù)的參數(shù)是值傳遞.如果想改變外面的變量,則需要傳遞變量的地址
=> Swift提供的inout關(guān)鍵字就可以實(shí)現(xiàn)地址傳遞
③ swift中函數(shù)可以嵌套使用 ( 即函數(shù)中包含函數(shù),但是不推薦該寫法)
20.函數(shù)的類型
1)函數(shù)類型的概念: 每個(gè)函數(shù)都有屬于自己的類型,由函數(shù)的參數(shù)類型和返回類型組成
2)函數(shù)類型 引發(fā)的應(yīng)用:
① 函數(shù)作為另外一個(gè)函數(shù)的參數(shù)
func exec(num1: Int, num2: Int, method: (Int, Int) -> Int) {
method(num1, num2) }
②函數(shù)作為另外一個(gè)函數(shù)的返回值
func getMethod(metName: String) -> (Int, Int) -> Int {}
21.枚舉的使用
1)概念介紹
枚舉定義了一個(gè)通用類型的一組相關(guān)的值,使你可以在你的代碼中以一個(gè)安全的方式來(lái)使用這些值
在 C/OC 語(yǔ)言中枚舉指定相關(guān)名稱為一組整型值
Swift 中的枚舉更加靈活,可以提供一個(gè)值是字符串,一個(gè)字符,或是一個(gè)整型值或浮點(diǎn)值
2)枚舉類型的語(yǔ)法
使用enum關(guān)鍵詞并且把它們的整個(gè)定義放在一對(duì)大括號(hào)內(nèi)
enum SomeEnumeration {
// enumeration definition goes here
}
3)枚舉類型的定義
enum CompassPoint {
case North
case South
case East
case West
}
注意:
①case關(guān)鍵詞表明新的一行成員值將被定義
②不像 C 和 OC 一樣,Swift 的枚舉成員在被創(chuàng)建時(shí)不會(huì)被賦予一個(gè)默認(rèn)的整數(shù)值
( 即 North,South,East和West不是隱式的等于0,1,2和3)
③定義枚舉時(shí)也可以只用一個(gè)Case,成員以逗號(hào)分隔
enum Planet {
case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune }
4)給枚舉類型賦值
枚舉類型賦值可以是字符串/字符/整型/浮點(diǎn)型
注意:如果有給枚舉類型賦值,則必須在枚舉類型后面明確說明具體的類型
enum CompassPoint : Int {
case North = 1
case South = 2
case East = 3
case West = 4
}
5)簡(jiǎn)單使用
根據(jù)枚舉值獲取"原始值”rawValue ,根據(jù)rawValue 獲取 枚舉值
注意: 枚舉值僅僅是一個(gè)抽象符號(hào), 并不代表任何類型; 如果想要綁定原始值, 必須指明枚舉的類型
22.結(jié)構(gòu)體
1.結(jié)構(gòu)體的基本使用:
1)概念介紹
結(jié)構(gòu)體(struct)是由一系列具有相同類型或不同類型的數(shù)據(jù)構(gòu)成的數(shù)據(jù)集合
注意:結(jié)構(gòu)體(struct)指的是一種數(shù)據(jù)結(jié)構(gòu),結(jié)構(gòu)體是值類型,在方法中傳遞時(shí)是值傳遞
2)結(jié)構(gòu)體的定義格式
struct 結(jié)構(gòu)體名稱 {
// 屬性和方法
}
2.結(jié)構(gòu)體擴(kuò)充構(gòu)造函數(shù):
須知: 默認(rèn)情況下, 結(jié)構(gòu)體會(huì)自動(dòng)創(chuàng)建一個(gè)"逐一構(gòu)造器” 目的就是為了讓所有"非可選"成員變量都能有值
但是為了讓我們?cè)谑褂媒Y(jié)構(gòu)體時(shí)更加的靈活,swift還可以對(duì)構(gòu)造函數(shù)進(jìn)行擴(kuò)充 。
擴(kuò)充的注意點(diǎn) :
①創(chuàng)建構(gòu)造函數(shù), 不要func關(guān)鍵字
② 在擴(kuò)充的構(gòu)造函數(shù)中必須保證所有的非可選成員變量是有值的 (每一個(gè)擴(kuò)充的構(gòu)造函數(shù)都要這樣做)
③ 擴(kuò)充的構(gòu)造函數(shù)會(huì)覆蓋原有的構(gòu)造函數(shù)(逐一構(gòu)造器)
3.結(jié)構(gòu)體擴(kuò)充函數(shù):
為了讓結(jié)構(gòu)體使用更加靈活,swift的結(jié)構(gòu)體中可以擴(kuò)充方法 :靜態(tài)方法(類型方法)和實(shí)例方法
注意:如果自定義方法中, 想要修改成員屬性的值,必須使用 mutating 關(guān)鍵字,因?yàn)? 結(jié)構(gòu)體是"值”類型
補(bǔ)充: 擴(kuò)充系統(tǒng)的結(jié)構(gòu)體方法,Swift也能幫我們達(dá)成,這個(gè)機(jī)制,叫做extension
23.類的基本使用
1)類的介紹和定義
Swift也是一門面向?qū)ο箝_發(fā)的語(yǔ)言,面向?qū)ο蟮幕A(chǔ)是類,類產(chǎn)生了對(duì)象
定義: class是Swift中的關(guān)鍵字,用于定義類
例如:
class 類名 : SuperClass { // 定義屬性和方法 }
2)定義類時(shí)的注意事項(xiàng):
原因:類是不會(huì)像結(jié)構(gòu)體一樣自動(dòng)生成"逐一構(gòu)造器"來(lái)保證"非可選"的成員屬性必須有值
所以, 解決方案:
①將"非可選"的屬性, 改為"可選”屬性
② 給"非可選"屬性設(shè)置默認(rèn)值
③在構(gòu)造函數(shù)中, 給"非可選"屬性賦值
注意: 定義的類,可以沒有父類.那么該類是rootClass
通常情況下,定義類時(shí).繼承自NSObject
3)類的構(gòu)造函數(shù)
介紹: ①構(gòu)造函數(shù)類似于OC中的初始化方法:init方法
②默認(rèn)情況下創(chuàng)建一個(gè)類時(shí),必然會(huì)調(diào)用一個(gè)構(gòu)造函數(shù)
③ 即便是沒有編寫任何構(gòu)造函數(shù),編譯器也會(huì)提供一個(gè)默認(rèn)的構(gòu)造函數(shù)。
④如果是繼承自NSObject,可以對(duì)父類的構(gòu)造函數(shù)進(jìn)行重寫
⑤注意:如果自定義了構(gòu)造函數(shù),會(huì)覆蓋init()方法.即不在有默認(rèn)的構(gòu)造函數(shù)
基本使用:
① 類的"非可選"屬性必須有值
② 如果不是在定義時(shí)初始化值,可以在構(gòu)造函數(shù)中賦值
24.字典轉(zhuǎn)模型(KVC)
1)字典轉(zhuǎn)模型(初始化時(shí)傳入字典)
去字典中取出的是,任意類型.可以通過as!轉(zhuǎn)成需要的類型,再賦值(不可以直接賦值)
class Person: NSObject {
var name :String
var age :Int
// 自定義構(gòu)造函數(shù),會(huì)覆蓋init()函數(shù)
init(dict : [String : Any]) {
name = dict["name"] as!String
age = dict["age"] as! Int
}
}
2)字典轉(zhuǎn)模型(利用KVC轉(zhuǎn)化)
注意: KVC并不能保證會(huì)給所有的屬性賦值 => 屬性需要有默認(rèn)值 或?yàn)榭蛇x類型
(基本數(shù)據(jù)類型默認(rèn)值設(shè)置為0,對(duì)象或者結(jié)構(gòu)體類型定義為可選類型即可(可選類型沒有賦值前為nil))
class Person: NSObject { // 結(jié)構(gòu)體或者類的類型,必須是可選類型.因?yàn)椴荒鼙WC一定會(huì)賦值
var name :String?
// 基本數(shù)據(jù)類型不能是可選類型,否則KVC無(wú)法轉(zhuǎn)化
var age :
Int = 0
// 自定義構(gòu)造函數(shù),會(huì)覆蓋init()函數(shù)
init(dict : [String : NSObject]) {
//必須先初始化對(duì)象(因?yàn)楦割愑袔湍阕龀跏蓟? super.init()
// 調(diào)用對(duì)象的KVC方法字典轉(zhuǎn)模型
setValuesForKeysWithDictionary(dict)
}
}
// 創(chuàng)建一個(gè)Person對(duì)象
let dict = ["name" : "sz", "age" : 18]
let p = Person(dict: dict)
25.類的析構(gòu)函數(shù)
須知:
Swift會(huì)自動(dòng)釋放不再需要的實(shí)例以釋放資源,具體是通過自動(dòng)引用計(jì)數(shù)(ARC)處理實(shí)例的內(nèi)存管理 當(dāng)引用計(jì)數(shù)為0時(shí),
系統(tǒng)會(huì)自動(dòng)調(diào)用析構(gòu)函數(shù)(不可以手動(dòng)調(diào)用)
那我們學(xué)習(xí)析構(gòu)函數(shù)的目的是:
通常在析構(gòu)函數(shù)中釋放一些資源(如移除通知等操作)
析構(gòu)函數(shù)的寫法:
deinit { // 執(zhí)行析構(gòu)過程 }
注意:析構(gòu)函數(shù)必須寫在類中。
class Person {
var name : String
var age : Int
init(name : String, age : Int) {
self.name = name
self.age = age
}
deinit{
print("Person-deinit")
}
}
var p : Person? = Person(name: "why", age: 18)
p = nil
26.類的屬性和方法
1)存儲(chǔ)屬性:
存儲(chǔ)屬性是最簡(jiǎn)單的屬性,它作為類實(shí)例的一部分,用于存儲(chǔ)常量和變量,可以給存儲(chǔ)屬性提供一個(gè)默認(rèn)值,也可以在初始化方法中對(duì)其進(jìn)行初始化
2)計(jì)算屬性:
計(jì)算屬性并不存儲(chǔ)實(shí)際的值,而是提供一個(gè)getter和一個(gè)可選的setter來(lái)間接獲取和設(shè)置其它屬性
計(jì)算屬性`一般`只提供getter方法
如果只提供getter,而不提供setter,則該計(jì)算屬性為只讀屬性,并且可以省略set{}
class Student : NSObject {
// 存儲(chǔ)屬性
var age : Int = 0
var name : String?
var chineseScore : Double = 0.0
var mathScore : Double = 0.0
// 計(jì)算屬性
var averageScore : Double {
get {
return (chineseScore + mathScore) / 2
}
// 沒有意義,因?yàn)橹螳@取值時(shí)依然是計(jì)算得到的
//newValue是系統(tǒng)分配的變量名,內(nèi)部存儲(chǔ)著新值
set {
self.averageScore = newValue
}
}
}
3)類屬性
類屬性是與類相關(guān)聯(lián)的,而不是與類的實(shí)例相關(guān)聯(lián)
(類屬性的設(shè)置和修改,需要通過類來(lái)完成)
所有的類和實(shí)例都共有一份類屬性.因此在某一處修改之后,該類屬性就會(huì)被修改 類屬性使用static來(lái)修飾
4)類的方法:
①對(duì)象方法
②類方法:
static 修飾 : 不能被子類重寫
class 修飾 : 可以被子類重寫
27.監(jiān)聽屬性改變
須知:
在OC中我們可以重寫set方法來(lái)監(jiān)聽屬性的改變,
Swift中可以通過屬性觀察者來(lái)監(jiān)聽和響應(yīng)屬性值的變化。
通常是監(jiān)聽存儲(chǔ)屬性和類屬性的改變.
(對(duì)于計(jì)算屬性,我們不需要定義屬性觀察者,因?yàn)槲覀兛梢栽谟?jì)算屬性的setter中直接觀察并響應(yīng)這種值的變化)
我們通過設(shè)置以下觀察方法來(lái)定義觀察者:
willSet:在屬性值被存儲(chǔ)之前設(shè)置。此時(shí)新屬性值作為一個(gè)常量參數(shù) 被傳入。該參數(shù)名默認(rèn)為newValue
didSet:在新屬性值被存儲(chǔ)后立即調(diào)用。與willSet相同,此時(shí)傳入的是屬性的舊值,默認(rèn)參數(shù)名為oldValue
注意:
① willSet與didSet只有在屬性第一次被設(shè)置時(shí)才會(huì)調(diào)用,在初始化時(shí),不會(huì)去調(diào)用這些監(jiān)聽方法
②可以給newValue / oldValue改名
class Person : NSObject {
var name : String? {
// 可以給newValue自定義名稱
willSet(new){ // 屬性即將改變,還未改變時(shí)會(huì)調(diào)用的方法
// 在該方法中有一個(gè)默認(rèn)的系統(tǒng)屬性newValue,用于存儲(chǔ)新值
print(name)
print(new)
}
// 可以給oldValue自定義名稱
didSet(old) { // 屬性值已經(jīng)改變了,會(huì)調(diào)用的方法
// 在該方法中有一個(gè)默認(rèn)的系統(tǒng)屬性oldValue,用于存儲(chǔ)舊值
print(name)
print(old)
}
}
var age : Int = 0
var height : Double = 0.0
}
let p : Person = Person()
// 在賦值時(shí),監(jiān)聽該屬性的改變
// 在OC中是通過重寫set方法
// 在swift中,可以給屬性添加監(jiān)聽器
p.name = "wsz"
//p.name = "why"
28.swift中自動(dòng)引用計(jì)數(shù)
Swift和OC一樣,采用自動(dòng)引用計(jì)數(shù)來(lái)管理內(nèi)容
( 當(dāng)有一個(gè)強(qiáng)引用指向某一個(gè)對(duì)象時(shí),該對(duì)象的引用計(jì)數(shù)會(huì)自動(dòng)+1,強(qiáng)引用消失則 -1 ,引用計(jì)數(shù)器為0則該對(duì)象自動(dòng)銷毀)
循環(huán)引用解決方案:
①weak : 和OC中的__weak一樣是一個(gè)弱引用.當(dāng)指向的對(duì)象銷毀時(shí),會(huì)自動(dòng)將指針指向nil
②unowned : 和OC中的__unsafe_unretained.當(dāng)對(duì)象銷毀時(shí)依然指向原來(lái)的位置(容易引起野指針)
29.三大特性
封裝
繼承
多態(tài) :父類指針, 指向子類, 來(lái)調(diào)用子類的方法
30.結(jié)構(gòu)體和類的區(qū)別
①結(jié)構(gòu)體有一個(gè)自動(dòng)生成的初始化器。新實(shí)例中各個(gè)屬性的初始值可以通過屬性的名稱傳遞到成員逐一初始化器之中。
②結(jié)構(gòu)體是值類型, 類是引用類型(結(jié)構(gòu)體的賦值意味著拷貝行為的發(fā)生)
③結(jié)構(gòu)體不能繼承
(意味著沒有多態(tài), 不具備運(yùn)行時(shí)強(qiáng)制類型轉(zhuǎn)換、使用析構(gòu)器和使用引用計(jì)數(shù)器等能力)