簡(jiǎn)單介紹一下Swift
Swift 語(yǔ)言由蘋(píng)果公司在 2014 年推出,用來(lái)撰寫(xiě) OS X 和 iOS 應(yīng)用程序,Swift語(yǔ)言讓?xiě)?yīng)用開(kāi)發(fā)更簡(jiǎn)單、更快、更穩(wěn)定,確保最終應(yīng)用有著更好的質(zhì)量更多了解Swift可以去 《The Swift Programming Language》中文版,這次分享給大家是Swift基礎(chǔ)知識(shí),如果你耐心看完本篇文章,并且可以理解Swift的編程技巧和方法,恭喜你可以順利的使用Swift開(kāi)發(fā)了,已經(jīng)掌握了Swift的基本語(yǔ)法,想要真正從事蘋(píng)果開(kāi)發(fā),還需要在以后的學(xué)習(xí)中不斷探索和挖掘Swift
在接下來(lái)的文章中,直接深入主題,不做過(guò)多沒(méi)必要的文字說(shuō)明,提高大家閱讀和吸收能力
一、常量和變量
常量:使用let來(lái)定義常量,定義之后不可以修改
變量:使用var來(lái)定義變量,定義之后可以修改
在使用過(guò)程中建議先定義常量,如果需要修改再修改為變量
import UIKit
let a : Int = 10
var b : Int = 20
b = 30 變量可以修改
// a = 20是錯(cuò)誤的,常量是不能修改的
二、數(shù)據(jù)類(lèi)型
1、類(lèi)型介紹
Swift中的數(shù)據(jù)類(lèi)型也有:整型/浮點(diǎn)型/對(duì)象類(lèi)型/結(jié)構(gòu)體類(lèi)型等,整型分為有符號(hào)整型和無(wú)符號(hào)整型,例如Int、UInt,浮點(diǎn)型分為Float和Double
// 定義一個(gè)Int類(lèi)型
var m : Int = 10
// 定義一個(gè)Double類(lèi)型
let n : Double = 3.14
2、類(lèi)型推導(dǎo)
Swift是強(qiáng)類(lèi)型的語(yǔ)言,Swift中任何一個(gè)標(biāo)識(shí)符都有明確的類(lèi)型,如果定義一個(gè)標(biāo)識(shí)符時(shí)有直接進(jìn)行賦值,那么標(biāo)識(shí)符后面的類(lèi)型可以省略,Swift會(huì)自動(dòng)根據(jù)后面的賦值來(lái)決定前面的標(biāo)識(shí)符的數(shù)據(jù)類(lèi)型,同時(shí)可以通過(guò)option+鼠標(biāo)左鍵來(lái)查看變量的數(shù)據(jù)類(lèi)型
Swift會(huì)自動(dòng)識(shí)別a是整數(shù),如果之后再賦值給a一個(gè)其他類(lèi)型(比如浮點(diǎn)型)數(shù)值,則會(huì)報(bào)錯(cuò)
var a = 20
// 正確寫(xiě)法
var b = 3.33
b = 6.66
3、基本運(yùn)算
Swift中在進(jìn)行基本運(yùn)算時(shí)必須保證類(lèi)型一致,否則會(huì)出錯(cuò),相同類(lèi)型之間才可以進(jìn)行運(yùn)算,Swift中沒(méi)有隱式轉(zhuǎn)換
Swift中數(shù)據(jù)類(lèi)型的轉(zhuǎn)化,Int類(lèi)型轉(zhuǎn)成Double類(lèi)型是Double(標(biāo)識(shí)符),Double類(lèi)型轉(zhuǎn)成Int類(lèi)型是Int(標(biāo)識(shí)符)
let a = 12
let b = 3.14
// 錯(cuò)誤寫(xiě)法,形同類(lèi)型之間才可以進(jìn)行運(yùn)算
// let c = a + b
// let c = a * b
// 正確寫(xiě)法,轉(zhuǎn)換類(lèi)型進(jìn)行運(yùn)算
let c = Double(a) + b
let d = a + Int(b)
三、邏輯分支
1、分支的了解
分支即if、switch、三目運(yùn)算符等判斷語(yǔ)句,通過(guò)分支語(yǔ)句可以控制程序的執(zhí)行流程
2、if分支語(yǔ)句
和OC不同,Swift判斷句可以不加(),在Swift的判斷句中必須有明確的真假,不再有非0即真,必須有明確的Bool值,Bool有兩個(gè)取值:false、true,沒(méi)有Yes、NO的使用
例1
確定值存在的判斷
let a = 12
// 錯(cuò)誤寫(xiě)法,在Swift的判斷句中必須有明確的真假,不再有非0即真
//if a {
// print("a")
//}
// 正確寫(xiě)法
if a > 9 {
print(a)
}
例2
可選類(lèi)型的判斷,判斷如果view有值,則設(shè)置背景
let view : UIView? = UIView()
// 錯(cuò)誤寫(xiě)法
//if view {
// view.backgroundColor = UIColor.red
//}
if view != nil {
view!.backgroundColor = UIColor.red
}
3、三目運(yùn)算符
Swift 中的 三目 運(yùn)算符和 OC 的用法是一樣的
var a = 12
var b = 24
var result = a > b ? a : b
println(result)
4、guard的使用
guard是很重要的,在以后的開(kāi)發(fā)中會(huì)經(jīng)常用到,來(lái)判斷該值是否是可選類(lèi)型,guard在Swift2.0就出現(xiàn)了,與if語(yǔ)句非常類(lèi)似,它設(shè)計(jì)的目的是提高程序的可讀性
guard語(yǔ)句必須帶有else語(yǔ)句,當(dāng)條件表達(dá)式為true時(shí)候跳過(guò)else語(yǔ)句中的內(nèi)容,執(zhí)行語(yǔ)句組內(nèi)容,條件表達(dá)式為false時(shí)候執(zhí)行else語(yǔ)句中的內(nèi)容,跳轉(zhuǎn)語(yǔ)句一般是return、break、continue和throw
例1
guard用法說(shuō)明
guard 條件表達(dá)式 else {
// 條換語(yǔ)句,走這里的都是錯(cuò)誤的,判斷不符合要求的
break
}
語(yǔ)句組,正確的執(zhí)行這里
例2
簡(jiǎn)單使用guard的用法
func gotToSchool(time:Int) -> Void {
guard time > 6 else {
print("去上學(xué)")
return
}
print("不去上學(xué)")
}
gotToSchool(time: 5)
5、switch分支
Switch作為選擇結(jié)構(gòu)中必不可少的語(yǔ)句也被加入到了Swift中,只要有過(guò)編程經(jīng)驗(yàn)的人對(duì)Switch語(yǔ)句都不會(huì)感到陌生,蘋(píng)果對(duì)Switch進(jìn)行了大大的增強(qiáng),使其擁有其他語(yǔ)言中沒(méi)有的特性
基本用法和OC用法一致,switch后可以不跟(),case后可以不跟break(默認(rèn)會(huì)有break)
例1
switch對(duì)整數(shù)的判斷
let sex = 0
switch sex {
case 0 :
print("男")
case 1 :
print("女")
default :
print("其他")
}
例2
一個(gè)case判斷中,可以判斷多個(gè)值,多個(gè)值以,隔開(kāi)
let sex = 0
switch sex {
case 0, 1:
print("正常人")
default:
print("其他")
}
例3
希望出現(xiàn)之前的case穿透,則可以使用關(guān)鍵字fallthrough
let sex = 0
switch sex {
case 0:
fallthrough
case 1:
print("正常人")
default:
print("其他")
}
Switch支持多種數(shù)據(jù)類(lèi)型
① 浮點(diǎn)型的switch判斷
let f = 3.14
switch f {
case 3.14:
print("π")
default:
print("not π")
}
② 支持字符串類(lèi)型
let m = 5
let n = 10
var result = 0
let opration = "+"
switch opration {
case "+":
result = m + n
case "-":
result = m - n
case "*":
result = m * n
case "/":
result = m / n
default:
result = 0
}
③ switch支持區(qū)間判斷
開(kāi)區(qū)間:0..<10 表示:0~9,不包括10
閉區(qū)間:0...10 表示:0~10
let score = 88
switch score {
case 0..<60:
print("不及格")
case 60..<80:
print("幾個(gè)")
case 80..<90:
print("良好")
case 90..<100:
print("優(yōu)秀")
default:
print("滿分")
}
四、循環(huán)
在開(kāi)發(fā)中經(jīng)常會(huì)需要循環(huán),常見(jiàn)的循環(huán)有:for、while、do while
1、for循環(huán)
① 傳統(tǒng)寫(xiě)法
for var i = 0; i < 10; i++ {
print(i)
}
② 區(qū)間for循環(huán)
for i in 0..<10 {
print(i)
}
for i in 0...10 {
print(i)
}
③ 特殊寫(xiě)法
如果在for循環(huán)中不需要用到下標(biāo)i,用`_`標(biāo)示
for _ in 0..<10 {
print("hello")
}
2、while和do while循環(huán)
① while的判斷句必須有正確的真假,沒(méi)有非0即真,while后面的()可以省略
var a = 0
while a < 10 {
a++
}
② do while循環(huán),使用repeat關(guān)鍵字來(lái)代替了do
let b = 0
repeat {
print(b)
b++
} while b < 20
五、字符串
OC和Swift中字符串的區(qū)別,在OC中字符串類(lèi)型時(shí)NSString,在Swift中字符串類(lèi)型是String,OC中字符串@"",Swift中字符串""
Swift中的String 是一個(gè)結(jié)構(gòu)體,性能更高,NSString 是一個(gè) OC 對(duì)象,性能略差,String 支持直接遍歷,Swift 提供了 String 和 NSString 之間的無(wú)縫轉(zhuǎn)換,可以使用as或者as?進(jìn)行轉(zhuǎn)換
1、遍歷字符串
// 字符串遍歷
var str = "Hello, Swift"
for c in str.characters {
print(c)
}
2、字符串拼接
例1
let str1 = "Hello"
let str2 = "World"
let str3 = str1 + str2
例2
let name = "why"
let age = 18
let info = "my name is \(name), age is \(age)"
例3
字符串的格式化
let min = 3
let second = 4
let time = String(format: "%02d:%02d", arguments: [min, second])
3、字符串的截取
Swift中提供了特殊的截取方式,該方式非常麻煩,簡(jiǎn)單的方式是將String轉(zhuǎn)成NSString來(lái)使用,在標(biāo)識(shí)符后加:as NSString即可
let myStr = "www.baidu.com"
var subStr = (myStr as NSString).substringFromIndex(4)
subStr = (myStr as NSString).substringToIndex(3)
subStr = (myStr as NSString).substringWithRange(NSRange(location: 4, length: 5))
六、數(shù)組
數(shù)組(Array)是一串有序的由相同類(lèi)型元素構(gòu)成的集合,數(shù)組中的集合元素是有序的,可以重復(fù)出現(xiàn),swift數(shù)組類(lèi)型是Array,是一個(gè)泛型集合
1、數(shù)組的初始化
數(shù)組分成可變數(shù)組和不可變數(shù)組,使用let修飾的數(shù)組是不可變數(shù)組,使用var修飾的數(shù)組是可變數(shù)組
// 定義一個(gè)可變數(shù)組,必須初始化才能使用
var array1 : [String] = [String]()
// 定義一個(gè)不可變數(shù)組
let array2 : [NSObject] = ["xiaoming", 18]
在聲明一個(gè)Array類(lèi)型的時(shí)候可以使用下列的語(yǔ)句之一
var stuArray1:Array<String>
var stuArray2: [String]
聲明的數(shù)組需要進(jìn)行初始化才能使用,數(shù)組類(lèi)型往往是在聲明的同時(shí)進(jìn)行初始化的
// 定義時(shí)直接初始化
var array = ["xm", "xl", "my"]
// 先定義,后初始化
var array : Array<String>
array = ["xm", "xl", "my"]
2、對(duì)數(shù)組的基本操作
// 添加數(shù)據(jù)
array.append("xiaoming")
// 刪除元素
array.removeFirst()
// 修改元素
array[0] = "xiaoming"
// 取值
array[1]
3、數(shù)組的遍歷
// 遍歷數(shù)組
for i in 0..<array.count {
print(array[i])
}
// forin方式,經(jīng)常使用
for item in array {
print(item)
}
// 設(shè)置遍歷的區(qū)間
for item in array[0..<2] {
print(item)
}
4、數(shù)組的合并
// 數(shù)組合并
// 注意:只有相同類(lèi)型的數(shù)組才能合并
var array = ["xm", "xl","my"]
var array1 = ["haha", "wsz"]
var array2 = array + array1;
// 不建議一個(gè)數(shù)組中存放多種類(lèi)型的數(shù)據(jù)
var array3 = [2, 3, "why"]
var array4 = ["yz", 23]
array3 + array4
七、字典
字典是由兩部分集合構(gòu)成的,一個(gè)是鍵(key)集合,一個(gè)是值(value)集合,鍵集合是不能有重復(fù)元素的,而值集合是可以重復(fù)的,鍵和值是成對(duì)出現(xiàn)的,Swift字典類(lèi)型是Dictionary,也是一個(gè)泛型集合
1、Swift中的可變和不可變字典,使用let修飾的數(shù)組是不可變字典,使用var修飾的數(shù)組是可變字典
// 定義一個(gè)可變字典
var dict1 : [String : NSObject] = [String : NSObject]()
// 定義一個(gè)不可變字典
let dict2 = ["name" : "xl", "age" : 18]
在聲明一個(gè)Dictionary類(lèi)型的時(shí)候可以使用下面的語(yǔ)句之一
var dict1: Dictionary<Int, String>
var dict2: [Int: String]
聲明的字典需要進(jìn)行初始化才能使用,字典類(lèi)型往往是在聲明的同時(shí)進(jìn)行初始化的
// 定義字典的同時(shí),進(jìn)行初始化
var dict = ["name" : "why", "age" : 18]
// swift中任意對(duì)象,通常不使用NSObject,使用AnyObject
var dict : Dictionary<String, AnyObject>
dict = ["name" : "why", "age" : 18]
2、字典的基本操作
// 添加數(shù)據(jù)
dict["height"] = 1.80
dict["weight"] = 65.0
// 刪除字段
dict.removeValueForKey("height")
// 修改字典
dict["name"] = "lmj"
// 查詢字典
dict["name"]
3、字典的遍歷
// 遍歷字典中所有的值
for value in dict.values {
print(value)
}
// 遍歷字典中所有的鍵
for key in dict.keys {
print(key)
}
// 遍歷所有的鍵值對(duì)
for (key, value) in dict {
print(key)
print(value)
}
4、字典的合并
// 字典的合并
var dict1 = ["name" : "xl", "age" : 20]
var dict2 = ["height" : 1.87, "phoneNum" : "+86 110"]
// 字典不可以相加合并
for (key, value) in dict1 {
dict2[key] = value
}
八、元組
元組是Swift中特有的,OC中并沒(méi)有相關(guān)類(lèi)型,類(lèi)似于數(shù)組或者字典,可以用于定義一組數(shù)據(jù),組成元組類(lèi)型的數(shù)據(jù)可以稱為“元素”
1、元組的定義
元組的常見(jiàn)寫(xiě)法
// 使用元組描述一個(gè)人的信息
("1001", "張三", 30, 90)
// 給元素加上元素名稱,之后可以通過(guò)元素名稱訪問(wèn)元素
(id:"1001", name:"張三", english_score:30, chinese_score:90)
2、元祖的簡(jiǎn)單使用
// 元祖使用
// 寫(xiě)法一:
let object = (xiaoming, "18")
print(object.0)
print(object.1)
// 寫(xiě)法二:
let object = (name : xiaoming, age : "18")
print(object.name)
print(object.age)
// 寫(xiě)法三:
let (name, age) = (xiaoming, "18")
print(name)
print(age)
九、可選類(lèi)型
在OC開(kāi)發(fā)中,如果一個(gè)變量暫停不使用,可以賦值為0(基本屬性類(lèi)型)或者賦值為空(對(duì)象類(lèi)型),在swift開(kāi)發(fā)中,nil也是一個(gè)特殊的類(lèi)型.因?yàn)楹驼鎸?shí)的類(lèi)型不匹配是不能賦值的(swift是強(qiáng)類(lèi)型語(yǔ)言),但是開(kāi)發(fā)中賦值nil,在所難免,因此推出了可選類(lèi)型
可選類(lèi)型的取值:空值或者有值
1、定義可選類(lèi)型
// 寫(xiě)法一:定義可選類(lèi)型
let name : Optional<String> = nil
// 寫(xiě)法二:定義可選類(lèi)型,語(yǔ)法糖(常用)
let name : String? = nil
2、可選類(lèi)型的使用
// 定義可選類(lèi)型
var string : Optional<String> = nil
// 給可選類(lèi)型賦值
string = "Hello world"
// 打印結(jié)果
print(string)
// 結(jié)果:Optional("Hello world")\n
// 取出可選類(lèi)型的真實(shí)值(解包)
print(string!)
// 結(jié)果:Hello world\n
// 注意:如果可選類(lèi)型為nil,強(qiáng)制取出其中的值(解包),會(huì)出錯(cuò)
string = nil
print(string!) // 報(bào)錯(cuò)
// 正確寫(xiě)法:
if string != nil {
print(string!)
}
// 簡(jiǎn)單寫(xiě)法:為了讓在if語(yǔ)句中可以方便使用string
// 可選綁定
if let str = string {
print(str)
}
十、函數(shù)
1、函數(shù)介紹
函數(shù)相當(dāng)于OC中的方法,函數(shù)的格式如下
func 函數(shù)名(參數(shù)列表) -> 返回值類(lèi)型 {
代碼塊
return 返回值
}
func是關(guān)鍵字,多個(gè)參數(shù)列表之間可以用逗號(hào)(,)分隔,也可以沒(méi)有參數(shù),使用箭頭“->”指向返回值類(lèi)型,如果函數(shù)沒(méi)有返回值,返回值為Void.并且“-> 返回值類(lèi)型”部分可以省略
2、常見(jiàn)的函數(shù)類(lèi)型
① 沒(méi)有參數(shù),沒(méi)用返回值
func about() -> Void {
print("iphone6s plus")
}
// 調(diào)用函數(shù)
about()
如果沒(méi)用返回值,Void可以寫(xiě)成()
func about1() -> () {
print("iphone6s plus")
}
// 如果沒(méi)有返回值,后面的內(nèi)容可以都不寫(xiě)
func about2() {
print("iphone6s plus")
}
about2()
② 有參數(shù),沒(méi)用返回值
func callPhone(phoneNum : String) {
print("打電話給\(phoneNum)")
}
callPhone("+86 110")
③ 沒(méi)用參數(shù),有返回值
func readMessage() -> String {
return "吃飯了嗎?"
}
var str = readMessage()
print(str)
④ 有參數(shù),有返回值
func sum(num1 : Int,num2 : Int) -> Int {
return num1 + num2
}
var result = sum(20,num2: 30)
print(result)
3、函數(shù)的使用
① 外部參數(shù)和內(nèi)部參數(shù)
在函數(shù)內(nèi)部可以看到的參數(shù),就是內(nèi)部參數(shù),在函數(shù)外面可以看到的參數(shù),就是外部參數(shù),默認(rèn)情況下,從第二個(gè)參數(shù)開(kāi)始,參數(shù)名稱既是內(nèi)部參數(shù)也是外部參數(shù),如果第一個(gè)參數(shù)也想要有外部參數(shù),可以設(shè)置標(biāo)簽,在變量名前加標(biāo)簽即可,如果不想要外部參數(shù),可以在參數(shù)名稱前加_
// num1和a是外部參數(shù)的名稱
func ride(num1 num1 : Int, a num2 : Int, b num3 : Int) -> Int {
return num1 * num2 * num3
}
var result1 = ride(num1: 20, a: 4, b: 5)
// 方法的重載:方法名稱相同,但是參數(shù)不同,可以稱之為方法的重載(了解)
func ride(num1: Int, _ num2 :Int) -> Int {
return num1 * num2
}
var result2 = ride(20, 20)
② 默認(rèn)參數(shù)
如果沒(méi)有傳入具體的參數(shù),可以使用默認(rèn)參數(shù)
func makecoffee(type :String = "卡布奇諾") -> String {
return "制作一杯\(type)咖啡。"
}
let coffee1 = makecoffee("鐵觀音")
let coffee2 = makecoffee()
③ 可變參數(shù)
Swift中函數(shù)的參數(shù)個(gè)數(shù)可以變化,它可以接受不確定數(shù)量的輸入類(lèi)型參數(shù),它們必須具有相同的類(lèi)型,我們可以通過(guò)在參數(shù)類(lèi)型名后面加入(...)的方式來(lái)指示這是可變參數(shù)
func sum(numbers:Double...) -> Double {
var total: Double = 0
for number in numbers {
total += number
}
return total
}
sum(100.0, 20, 30)
sum(30, 80)
④ 引用類(lèi)型(指針的傳遞)
默認(rèn)情況下,函數(shù)的參數(shù)是值傳遞,如果想改變外面的變量,則需要傳遞變量的地址,必須是變量,因?yàn)樾枰趦?nèi)部改變其值,Swift提供的inout關(guān)鍵字就可以實(shí)現(xiàn)
// 函數(shù)一:值傳遞
func swap(var a : Int, var b : Int) {
let temp = a;
a = b;
b = temp
print("a:\(a), b:\(b)")
}
var a = 10
var b = 20
swap(a, b: b)
print("a:\(a), b:\(b)")
// 函數(shù)二:指針的傳遞
func swap1(inout a : Int, inout b : Int) {
let temp = a
a = b
b = temp
print("a:\(a), b:\(b)")
}
swap1(&a, b: &b)
print("a:\(a), b:\(b)")
⑤ 函數(shù)的嵌套使用
swift中函數(shù)可以嵌套使用,即函數(shù)中包含函數(shù),但是不推薦該寫(xiě)法
十一、類(lèi)的使用
1、類(lèi)的介紹和定義
Swift也是一門(mén)面向?qū)ο箝_(kāi)發(fā)的語(yǔ)言,面向?qū)ο蟮幕A(chǔ)是類(lèi),類(lèi)產(chǎn)生了對(duì)象,class是Swift中的關(guān)鍵字,用于定義類(lèi)
定義的類(lèi),可以沒(méi)有父類(lèi).那么該類(lèi)是rootClass,通常情況下,定義類(lèi)時(shí),繼承自NSObject(非OC的NSObject)
class 類(lèi)名 : SuperClass {
// 定義屬性和方法
}
2、定義類(lèi)的屬性
Swift中類(lèi)的屬性有多種:存儲(chǔ)屬性,存儲(chǔ)實(shí)例的常量和變量;計(jì)算屬性,通過(guò)某種方式計(jì)算出來(lái)的屬性;類(lèi)屬性,與整個(gè)類(lèi)自身相關(guān)的屬性
① 存儲(chǔ)屬性
存儲(chǔ)屬性是最簡(jiǎn)單的屬性,它作為類(lèi)實(shí)例的一部分,用于存儲(chǔ)常量和變量,可以給存儲(chǔ)屬性提供一個(gè)默認(rèn)值,也可以在初始化方法中對(duì)其進(jìn)行初始化
// 給存儲(chǔ)屬性賦值
stu.age = 10
stu.name = "xiaoming"
stu.chineseScore = 89.0
stu.mathScore = 98.0
② 計(jì)算屬性
計(jì)算屬性并不存儲(chǔ)實(shí)際的值,而是提供一個(gè)getter和一個(gè)可選的setter來(lái)間接獲取和設(shè)置其它屬性,計(jì)算屬性一般只提供getter方法,如果只提供getter,而不提供setter,則該計(jì)算屬性為只讀屬性,并且可以省略get{}
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
}
// 沒(méi)有意義,因?yàn)橹螳@取值時(shí)依然是計(jì)算得到的
// newValue是系統(tǒng)分配的變量名,內(nèi)部存儲(chǔ)著新值
set {
self.averageScore = newValue
}
}
}
③ 類(lèi)屬性
類(lèi)屬性是與類(lèi)相關(guān)聯(lián)的,而不是與類(lèi)的實(shí)例相關(guān)聯(lián),類(lèi)屬性的設(shè)置和修改,需要通過(guò)類(lèi)來(lái)完成,類(lèi)屬性使用static來(lái)修飾
class Student : NSObject {
// 類(lèi)屬性
static var corseCount : Int = 0
}
// 設(shè)置類(lèi)屬性的值
Student.corseCount = 3
// 取出類(lèi)屬性的值
print(Student.corseCount)
④ 監(jiān)聽(tīng)屬性的改變
在OC中我們可以重寫(xiě)set方法來(lái)監(jiān)聽(tīng)屬性的改變,在Swift中可以通過(guò)屬性觀察者來(lái)監(jiān)聽(tīng)和響應(yīng)屬性值的變化,通常是監(jiān)聽(tīng)存儲(chǔ)屬性和類(lèi)屬性的改變,(對(duì)于計(jì)算屬性,我們不需要定義屬性觀察者,因?yàn)槲覀兛梢栽谟?jì)算屬性的setter中直接觀察并響應(yīng)這種值的變化)
willSet:在屬性值被存儲(chǔ)之前設(shè)置,此時(shí)新屬性值作為一個(gè)常量參數(shù)被傳入,該參數(shù)名默認(rèn)為newValue,我們可以自己定義該參數(shù)名;didSet:在新屬性值被存儲(chǔ)后立即調(diào)用,與willSet相同,此時(shí)傳入的是屬性的舊值,默認(rèn)參數(shù)名為oldValue;
willSet與didSet只有在屬性第一次被設(shè)置時(shí)才會(huì)調(diào)用,在初始化時(shí),不會(huì)去調(diào)用這些監(jiān)聽(tīng)方法
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)聽(tīng)該屬性的改變
// 在OC中是通過(guò)重寫(xiě)set方法
// 在swift中,可以給屬性添加監(jiān)聽(tīng)器
p.name = "xiaoming"
十二、類(lèi)的構(gòu)造函數(shù)
構(gòu)造函數(shù)類(lèi)似于OC中的初始化方法init方法,默認(rèn)情況下載創(chuàng)建一個(gè)類(lèi)時(shí),必然會(huì)調(diào)用一個(gè)構(gòu)造函數(shù),即便是沒(méi)有編寫(xiě)任何構(gòu)造函數(shù),編譯器也會(huì)提供一個(gè)默認(rèn)的構(gòu)造函數(shù),如果是繼承自NSObject,可以對(duì)父類(lèi)的構(gòu)造函數(shù)進(jìn)行重寫(xiě)
1、構(gòu)造函數(shù)的基本使用
① 類(lèi)的屬性必須有值,如果不是在定義時(shí)初始化值,可以在構(gòu)造函數(shù)中賦值
class Person: NSObject {
var name : String
var age : Int
// 重寫(xiě)了NSObject(父類(lèi))的構(gòu)造方法
override init() {
name = ""
age = 0
}
}
// 創(chuàng)建一個(gè)Person對(duì)象
let p = Person()
② 初始化時(shí)給屬性賦值
我們?cè)趧?chuàng)建一個(gè)對(duì)象時(shí)就會(huì)給屬性賦值,可以自定義構(gòu)造函數(shù),如果自定義了構(gòu)造函數(shù),會(huì)覆蓋init()方法,即不在有默認(rèn)的構(gòu)造函數(shù)
class Person: NSObject {
var name : String
var age : Int
// 自定義構(gòu)造函數(shù),會(huì)覆蓋init()函數(shù)
init(name : String, age : Int) {
self.name = name
self.age = age
}
}
// 創(chuàng)建一個(gè)Person對(duì)象
let p = Person(name: "xiaoming", age: 18)
③ 字典轉(zhuǎn)模型(初始化時(shí)傳入字典)
例1
class Person: NSObject {
var name : String
var age : Int
// 自定義構(gòu)造函數(shù),會(huì)覆蓋init()函數(shù)
init(dict : [String : NSObject]) {
name = dict["name"] as! String
age = dict["age"] as! Int
}
}
// 創(chuàng)建一個(gè)Person對(duì)象
let dict = ["name" : "xiaoming", "age" : 18]
let p = Person(dict: dict)
例2
利用KVC字典轉(zhuǎn)模型
class Person: NSObject {
// 結(jié)構(gòu)體或者類(lèi)的類(lèi)型,必須是可選類(lèi)型,因?yàn)椴荒鼙WC一定會(huì)賦值
var name : String?
// 基本數(shù)據(jù)類(lèi)型不能是可選類(lèi)型,否則KVC無(wú)法轉(zhuǎn)化
var age : Int = 0
// 自定義構(gòu)造函數(shù),會(huì)覆蓋init()函數(shù)
init(dict : [String : NSObject]) {
// 必須先初始化對(duì)象
super.init()
// 調(diào)用對(duì)象的KVC方法字典轉(zhuǎn)模型
setValuesForKeysWithDictionary(dict)
}
}
// 創(chuàng)建一個(gè)Person對(duì)象
let dict = ["name" : "xiaoming", "age" : 18]
let p = Person(dict: dict)
十三、閉包
Swift閉包和OC中的block非常相似,OC中的block是匿名的函數(shù),Swift中的閉包是一個(gè)特殊的函數(shù),block和閉包都經(jīng)常用于回調(diào)
1、OC中Block的使用
首先介紹一下OC中Block寫(xiě)法
① 第一種Block方式
@property (nonatomic, copy) void(^callBack)(NSString *name);
callBack 是block對(duì)象
回調(diào)方法
if(_callBack){
_callBack(name)
}
② 第二種Block方式
typedef void(^CallBack)(NSString *str);
@property (nonatomic, copy) CallBack callback;
callback是block對(duì)象
回調(diào)方法
if(_callBack){
_callBack(name)
}
③ 第三種Block方式
- (void)setUpWith:(void(^)(NSString *str))callback;
callback是block對(duì)象
回調(diào)方法
if(_callBack){
_callBack(name)
}
總結(jié)
Block的寫(xiě)法:
類(lèi)型:
返回值類(lèi)型(^block的名稱)(block的參數(shù))
值:
^(參數(shù)列表) {
// 執(zhí)行的代碼
};
2、Swift中閉包的使用
① 第一種閉包方式
var callBack : (()->())?
② 第二種閉包方式
func loadRequest(callBack : ()->()){
callBack()
}
總結(jié)
閉包的寫(xiě)法:
callBack: (形參列表) -> (返回值類(lèi)型)
類(lèi)型:(形參列表) -> (返回值類(lèi)型)
值:
{
(形參) -> 返回值類(lèi)型 in
// 執(zhí)行代碼
}
閉包的簡(jiǎn)寫(xiě),如果閉包沒(méi)有參數(shù),沒(méi)有返回值,in和in之前的內(nèi)容可以省略
尾隨閉包寫(xiě)法
① 如果閉包是函數(shù)的最后一個(gè)參數(shù),則可以將閉包寫(xiě)在()后面
httpTool.loadRequest() {
print("回到主線程", NSThread.currentThread());
}
② 如果函數(shù)只有一個(gè)參數(shù),并且這個(gè)參數(shù)是閉包,那么()可以不寫(xiě)
// 開(kāi)發(fā)中建議該寫(xiě)法
httpTool.loadRequest {
print("回到主線程", NSThread.currentThread());
}
3、閉包的循環(huán)引用
如果在HttpTool中有對(duì)閉包進(jìn)行強(qiáng)引用,則會(huì)形成循環(huán)引用,在Swift中檢測(cè)一個(gè)對(duì)象是否銷(xiāo)毀,可以實(shí)現(xiàn)對(duì)象的deinit函數(shù)
// 析構(gòu)函數(shù)(相當(dāng)于OC中dealloc方法)
deinit {
print("ViewController----deinit")
}
4、swift中解決循環(huán)引用的方式
① 使用weak,對(duì)當(dāng)前控制器使用弱引用
但是因?yàn)閟elf可能有值也可能沒(méi)有值,因此weakSelf是一個(gè)可選類(lèi)型,在真正使用時(shí)可以對(duì)其強(qiáng)制解包(該處強(qiáng)制解包沒(méi)有問(wèn)題,因?yàn)榭刂破饕欢ù嬖?否則無(wú)法調(diào)用所在函數(shù))
解決一
weak var weakSelf = self
httpTool.loadData {
print("加載數(shù)據(jù)完成,更新界面:", NSThread.currentThread())
weakSelf!.view.backgroundColor = UIColor.redColor()
}
② 可以寫(xiě)在閉包中,并且在閉包中用到的self都是弱引用
解決二
httpTool.loadData {[weak self] () -> () in
print("加載數(shù)據(jù)完成,更新界面:", NSThread.currentThread())
self!.view.backgroundColor = UIColor.redColor()
}
③ 使用關(guān)鍵字unowned
unowned 更像OC中的 unsafe_unretained,unowned 表示即使它原來(lái)引用的對(duì)象被釋放了,仍然會(huì)保持對(duì)被已經(jīng)釋放了的對(duì)象的一個(gè) "無(wú)效的" 引用,它不能是 Optional 值,也不會(huì)被指向 nil
解決三
httpTool.loadData {[unowned self] () -> () in
print("加載數(shù)據(jù)完成,更新界面:", NSThread.currentThread())
self.view.backgroundColor = UIColor.redColor()
}
十四、懶加載
swift中也有懶加載的方式,希望所有的對(duì)象在使用時(shí)才真正加載到內(nèi)存中,和OC不同的是swift有專門(mén)的關(guān)鍵字來(lái)實(shí)現(xiàn)懶加載,lazy關(guān)鍵字可以用于定義某一個(gè)屬性懶加載
1、懶加載普通方式
lazy var 變量:類(lèi)型 = 系統(tǒng)類(lèi)()
lazy var button:UIButton = UIButton()
2、懶加載升級(jí)方式
lazy var array : [String] = {
() -> [String] in
return ["xiaoming", "xl", "lisi"]
}()
心得體會(huì):
Swift好用,如果你讀完本篇文章基本上掌握了Swift基礎(chǔ)知識(shí),剩下的就是實(shí)戰(zhàn)了,實(shí)戰(zhàn)會(huì)增加你編寫(xiě)Swift的能力,對(duì)Swift有更深的理解,后期也會(huì)補(bǔ)充新的Swift知識(shí),也會(huì)分享自己的開(kāi)源Swift項(xiàng)目共大家學(xué)習(xí)討論,請(qǐng)關(guān)注下我的github賬號(hào)lb2281075105,開(kāi)始分享自己的項(xiàng)目和Demo,如果更好的意見(jiàn)請(qǐng)及時(shí)給我說(shuō)哦,合理我會(huì)毫不猶豫采納,謝謝,您的點(diǎn)贊會(huì)更加激勵(lì)我的熱情。