簡介
Swift是蘋果公司推出的可用于開發(fā)Mac OS和iOS系統(tǒng)上的應(yīng)用的專用編程語言妹笆,它相比于Objective-C(以下簡稱OC)語言佣盒,更加嚴(yán)謹(jǐn)官份,是一種強(qiáng)語言优妙。
使用工具
首先,先介紹使用的工具符隙,畢竟一個(gè)方便的工具可以大大提高效率,而這里學(xué)習(xí)Swift最快速地工具就是playground
1
playground 游樂場(chǎng)垫毙,可以立刻獲得編譯后的效果
快速入門
- 創(chuàng)建對(duì)象
- OC
[[UIView alloc] initWithXXX:];
- Swift
UIView(xxx)
2
- 調(diào)用方法
- OC
[UIColor redColor]
- OC
- Swift
UIColor.redColor
- 枚舉
- OC
UIButtonTypeContactAdd
- Swift
UIButtonType.ContactAdd
- OC
輸出
- OC
NSLog(@"Hellow World");
- Swift
print("Hellow World");
常量變量
- OC
- 變量
int a = 20;
- 常量
const int a = 20
- 變量
- Swift
- 在Swift語言中霹疫,所有的類型的第一個(gè)字母均是大寫,Int,Double...
- 變量 - var
var a1:Int = 20
- 常量 - let
let a1:Int = 20
3
-
快捷鍵: 按住option,點(diǎn)擊综芥,可以查看他的信息
4 -
數(shù)據(jù)類型
- OC中的數(shù)據(jù)類型首字母變成大寫丽蝎,就是Swift中的數(shù)據(jù)類型
-
注意點(diǎn):
- 在Swift開發(fā)中,一般情況下應(yīng)該先用let膀藐,只要在需要修改數(shù)據(jù)時(shí)才改用var,使用let的
好處
是屠阻,避免數(shù)據(jù)被修改,可以保證數(shù)據(jù)安全性
- 在Swift開發(fā)中,一般情況下應(yīng)該先用let膀藐,只要在需要修改數(shù)據(jù)時(shí)才改用var,使用let的
-
類型推斷
- Swift中如果在定義變量/常量時(shí)進(jìn)行初始化, 那么數(shù)據(jù)類型可以不用寫, 系統(tǒng)會(huì)自動(dòng)根據(jù)右邊的復(fù)制推導(dǎo)出變量/常量的類型
- Swift開發(fā)中
能不寫
數(shù)據(jù)類型就不寫
數(shù)據(jù)類型, 盡量使用編譯器的自動(dòng)推導(dǎo) - 只有當(dāng)我們需要明確的指定數(shù)據(jù)的長度, 獲取需要先定義再初始化時(shí)才明確的指定數(shù)據(jù)類型
- 使用自動(dòng)類型推導(dǎo)
好處
: 大大降低
代碼中的冗余
代碼 - 指定類型
let num:Int = 20
- 自動(dòng)推導(dǎo)
let num = 20
5
- 類型轉(zhuǎn)換:
- OC中有顯示轉(zhuǎn)換和隱式轉(zhuǎn)換
double value = 10.1 + 9
- Swift中只有顯示轉(zhuǎn)換沒有隱式轉(zhuǎn)換, 也就是說只有相同類型的數(shù)據(jù)才能進(jìn)行賦值和計(jì)算
- OC中有顯示轉(zhuǎn)換和隱式轉(zhuǎn)換
元組
-
復(fù)合
數(shù)據(jù)類型 - 只要將多個(gè)相同或者不同的數(shù)據(jù)用
()
括起來就是元祖 - 優(yōu)點(diǎn): 在以前沒有元祖之前C和OC語言是通過傳入指針或者返回結(jié)構(gòu)體的方式來返回多個(gè)值的, 而有了元祖之后就可以實(shí)現(xiàn)讓一個(gè)函數(shù)返回多個(gè)值
let number1:(Int,Double,CGFloat,NSInteger) = (1,1.1,1.11,2)
number1.0
number1.1
number1.2
number1.3
// 給元組的元素起名
/*
元祖的其它定義方式:指明應(yīng)用元祖元素的名稱
*/
let person = (name:"tym", age:18, score:100.0)
person.name
person.age
person.score
// 提取元組的數(shù)據(jù)
/*
元祖的其它定義方式:
通過指定的名稱提取元祖對(duì)應(yīng)的值, 會(huì)將對(duì)應(yīng)位置的值 賦值給對(duì)應(yīng)位置的名稱
*/
let (name, age, score) = ("tym", 18, 100.0)
name
age
score
/*
如果不關(guān)心元祖中的某個(gè)值可以利用_通配符來忽略提取
*/
let (name1 , age1 , _) = ("tym", 18, 99.8)
print(name1)
print(age1)
分支
-
Bool 類型
- C 和OC并沒真正的Bool類型额各,非0即真
- OC語言的Bool類型YES/NO是
typedef signed char BOOL;
- OC語言的Bool類型YES/NO是
- Swift引入了真正的Bool類型
- Swift中沒有C和OC中非零即真的概念
- Swfit中邏輯值只有兩個(gè)true/false
- C 和OC并沒真正的Bool類型额各,非0即真
-
if語句
- Swift
- 大部分用法和OC中一致
- Swift中
條件
語句可以不用寫()
- OC中如果if后面只有一條語句, 那么{}可以省略, 但是Swift不行
- OC中條件語句可以是任何數(shù)值, OC中非0即真, YES/NO
- Swift中
條件
語句的取值必須
是Bool
類型, 也就是說Swift中提供了真正的Bool類型, true/false
- Swift
let number = 10
//if number = 10 // Swift有效的避免了這種問題
if number == 10
{
print(number)
}
- 三目運(yùn)算符
- 大部分用法和OC一樣
- 條件表達(dá)式只能是Bool值
print(age >= 18 ? "開網(wǎng)卡":"回家")
- switch語句
- 大部分用法和OC一樣
- Swift中
條件
語句可以不用寫()
-
OC
中default
可以省略
, 而Swift
中大部分情況不能省略,而且default只能夠放在最后面的位置 - OC中default的位置可以隨便寫, 而Swift不可以
- OC中每個(gè)case后面必須加上break, 否則會(huì)出現(xiàn)
穿透
, 而Swift
不會(huì)穿透, 也就是說不用寫break
- OC中要在case中間定義變量必須加上{}, 否則作用域混亂, 而Swift不用
- Swift可以
判斷
對(duì)象類型国觉,區(qū)間和元祖,OC只可以判斷整數(shù)
let score = 100
switch score
{
case 59:
print("不及格")
case 100:
print("滿分")
default:
print("Other")
}
var rank = "A"
switch rank{
case "A": //相當(dāng)于if
print("優(yōu)")
case "B": // 相當(dāng)于else if
print("優(yōu)")
case "C": // 相當(dāng)于else if
print("優(yōu)")
default: // 相當(dāng)于else
print("沒有評(píng)級(jí)")
}
/*
因?yàn)椴荒艽┩杆圆荒苓@么寫
var rank1 = "A"
switch rank1{
case "A":
case "B":
print("優(yōu)")
case "C":
print("優(yōu)")
default:
print("沒有評(píng)級(jí)")
}
*/
//只能這么寫
var rank1 = "A"
switch rank1{
case "A", "B": // 注意OC不能這樣寫
print("優(yōu)")
case "C":
print("差")
default:
print("沒有評(píng)級(jí)")
}
- 區(qū)間
- 閉區(qū)間: 0...10 , 取值范圍0~10,包含頭包含尾
- 半閉區(qū)間: 0..<10 , 取值范圍0~9,包含頭不包含尾
switch score
{
case 0..<60: // 0 ~ 59
print("不及格")
case 60..<80: // 60 ~ 79
print("良好")
case 80..<100: // 80 ~ 99
print("優(yōu)秀")
default:
print("滿分")
}
// 判斷元組
let point = (100, 50)
switch point
{
case (0,0):
print("原點(diǎn)")
case (50,50):
print("中點(diǎn)")
case (100,100):
print("右下角")
default:
print("Other")
}
// 值綁定
var point = (1, 10)
switch point{
case (var x, 10): // 會(huì)將point中X的值賦值給X
print("x= \(x)")
case (var x, var y): // 會(huì)將point中X,Y的值賦值給X虾啦,Y
print("x= \(x) y= \(y)")
case var( x, y):
print("x= \(x) y= \(y)")
default:
print("Other")
}
// 根據(jù)條件綁定
var point = (100, 10)
switch point{
// 只有where后面的條件表達(dá)式為真才賦值并執(zhí)行case后的語句
case var(x, y) where x > y:
print("x= \(x) y= \(y)")
default:
print("Other")
}
可選類型
- 可選類型
- 一個(gè)變量
可以有值
也可以沒有值
, 我們就稱之為可選類型 - 在Swift中如果使用一個(gè)可選類型的變量/常量, 必須
解包
操作- 解包: 只需要在變量/常量后面加上 !
- !含義: 代表
告訴系統(tǒng)
該變量/常量中一定有值
, 如果強(qiáng)制解包一個(gè)沒有值的常量/變量,那么會(huì)報(bào)錯(cuò)
- 優(yōu)點(diǎn): 提高
代碼閱讀性
- 格式:
- 修飾符 變量名稱:Optional<數(shù)據(jù)類型>
- 修飾符 變量名稱: 數(shù)據(jù)類型?
- 語法糖: 因?yàn)樵赟wift中可選類型用得非常非常多, 所以為了簡化代碼, Swift提供了一個(gè)語法糖, 可以用?
代替
Optional<數(shù)據(jù)類型>
- 一個(gè)變量
Snip20151018_11.png
7
- 注意:
- 在開發(fā)中一般情況下盡量不要
強(qiáng)制
解包一個(gè)可選類型, 否則會(huì)引發(fā)錯(cuò)誤 - 可選綁定: 為了更
安全
的解析可選類型的值, 一般情況下使用可選綁定- 如果沒有值就不會(huì)做任何操作, 如果
有值
會(huì)返回true
并將optValue的值賦
值給result執(zhí)行大括號(hào)中的內(nèi)容
- 如果沒有值就不會(huì)做任何操作, 如果
- 在開發(fā)中一般情況下盡量不要
/*
// 這樣不嚴(yán)謹(jǐn)
let url = NSURL(string: "http://www.hao123.com/")
print(url)
let request = NSURLRequest(URL: url!)
*/
let url = NSURL(string: "http://www.hao123.com")
print(url)
if url != nil
{
let request = NSURLRequest(URL: url!)
}
// 可選綁定: 如果url不為nil, 系統(tǒng)內(nèi)部就會(huì)自動(dòng)將解包之后的值賦值給temp, 并且只有temp有值時(shí)才會(huì)執(zhí)行{}中的代碼
// Swift開發(fā)中推薦這種寫法
if let temp = url
{
let request = NSURLRequest(URL: temp)
}
循環(huán)語句
- for循環(huán)
- 傳統(tǒng)的for
/*:
傳統(tǒng)for
* 基本用法和OC一致
* for后面的()可以省略
* for后面的{}不可用省略
* Swift開發(fā)中不建議使用傳統(tǒng)for循環(huán)
*/
for var i = 0; i < 10; i++
{
print(i)
}
// 一直循環(huán)
//for ;;
//{
// print("---")
//}
- 推薦的for循環(huán)形式
// Swift開發(fā)者中推薦的for循環(huán)格式
for i in 0..<10
{
print(i)
}
- while 循環(huán)
- 基本用法和OC一致
var number = 0
while number < 10
{
print(number)
number++
}
- do-while 循環(huán)
- 基本用法和OC一致
- Swift2.0開始dowhile循環(huán)中沒有do, 只有repeat, 因?yàn)閐o被作用異常處理
var index = 0
repeat{
print(index)
index++
}while index < 10
數(shù)組
- 格式 var arr: Array<Int> / var arr: [Int]
- 可變和不可變 var/let
// 1.遍歷數(shù)組(取值)
arr[0]
for item in arr
{
print(item)
}
// 2.添加
arr.append(3)
// 3.修改
arr[1] = 9
// 4.刪除
arr.removeAtIndex(0)
// 5.合并
var arr1 = [3, 5, 7]
arr += arr1
// 6.Swift特殊
for item in arr[0..<2] // 0~1
{
print(item)
}
//arr.removeRange(Range(start: 0, end: 2))
//arr
// 通過觀察可以發(fā)現(xiàn)Range其實(shí)就是一個(gè)半閉區(qū)間
arr.removeRange(0..<2)
arr
arr += arr1[0..<2]
字典
- 格式 var dict: Dictionary<String, String>
- 注意: 將OC的{}換成了[]
- 可變和不可變 var/let
var dictTest: Dictionary<String,String>
var dictTest2: [String: String]
var dict = ["name":"tym", "age":"18"]
// 企業(yè)開發(fā)中字典使用的最多的類型就是 [String: NSObject] 類型
var dict2 = ["name":"tym", "age":"18", "score":99.99]
// 取值
dict2["age"]
// 修改
dict2["age"] = 20
dict2
// 增加
dict2["rank"] = 10
dict2
// 刪除
dict2.removeValueForKey("name")
dict2
// removeValueForKey返回一個(gè)可選類型, 如果字典中不存在需要?jiǎng)h除的key, 那么返回nil并且不會(huì)執(zhí)行任何操作, 如果存在則刪除key對(duì)應(yīng)的值, 并且返回被刪除的值
var dict14 = ["name":"lnj", "age":30]
if let orignal = dict14.removeValueForKey("names")
{
print(dict14)
print(orignal)
}
print(dict14)
var dict15 = ["name":"lnj", "age":30]
dict15.removeAll(keepCapacity: true)
// 遍歷
var dict17 = ["name":"lnj", "age":30]
for key in dict17.keys
{
print("key = \(key)")
}
var dict18 = ["name":"lnj", "age":30]
for value in dict18.values
{
print("value = \(value)")
}
// Swift寫法
// 系統(tǒng)會(huì)自動(dòng)將字典中的key賦值給元祖中的第一個(gè)遍歷, 會(huì)自動(dòng)將字典中的value賦值給元祖中的第二個(gè)遍歷
for (key,object) in dict2
{
print(key)
print(object)
}
// 合并
var dict3 = ["name":"tym", "sex":"M", "height":179.9]
var dict4 = ["weight":120, "score":100.0]
for (key,value) in dict4
{
dict3[key] = value
}
dict3
字符串
- OC的字符串是NSString, Swift的字符串String
- OC的字符串是一個(gè)對(duì)象, Swift字符串是一個(gè)
結(jié)構(gòu)體
, 效率更高 - OC中的字符串是一個(gè)\0結(jié)尾, Swift字符串
不是
以\0結(jié)尾 - Swift中的字符串支持遍歷
let str = "Hi, \0 Tym"
// 遍歷字符串
for c in str.characters
{
print(c)
}
// 字符串拼接
var str2 = "Hello,World!"
str2 += str
// 字符串格式化
let name = "tym"
let age = 18
let res = "name: \(name) , age: \(age)"
// 2015-10-19 13:55
let str3 = String(format: "%d-%02d-%02d %02d:%02d", arguments: [2015,10,19,13,55])
// 截取字符串
// 提示: 在Swift開發(fā)中, 我們經(jīng)常需要將Swift的字符串轉(zhuǎn)換為OC的字符串來操作, 并且Swift自身也意識(shí)到了這一點(diǎn), 所以在OC字符串和Swift的字符串之間轉(zhuǎn)換相當(dāng)簡單
let str4 = "ttyymm"
let str5: NSString = str4
str5.substringToIndex(4)
str5.substringWithRange(NSMakeRange(0, 1))
// 計(jì)算字符串長度
var stringValue = "abc李"
print(stringValue.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
// 打印結(jié)果6, 和C語言一樣計(jì)算字節(jié)數(shù)
// as 就是把什么當(dāng)做什么
(str4 as NSString).substringFromIndex(2)
函數(shù)
- 格式
func 函數(shù)名稱(形參列表) ->返回值類型
{
代碼
}```
* Void == ()
```objc
// 1.沒有參數(shù)沒有返回值,沒有返回值時(shí)可不寫返回值
func say() -> Void
{
print("Hi!")
}
func say1() -> ()
{
print("Hi!")
}
say1()
func say2()
{
print("Hi!")
}
say2()
// 2.有參數(shù)沒有返回值
// Swift2.0開始, 會(huì)自動(dòng)將形參列表的第二個(gè)參數(shù)名稱作為標(biāo)簽
// Swift2.0之前是沒有這個(gè)特性的, 在Swift2.0之前如果需要顯示標(biāo)簽需要在形參名稱前面加上#
func sum(num1:Int, num2:Int)
{
print(num1 + num2)
}
sum(10, num2: 20)
// 3.沒有參數(shù)有返回值
func getNumber() -> Int
{
return 998
}
getNumber()
// 4.有參數(shù)有返回值
func sum2(num1:Int, num2:Int) -> Int
{
return num1 + num2
}
print(sum2(11, num2: 22))
- 內(nèi)部和外部參數(shù)
- 默認(rèn)情況下所有形參都是
內(nèi)部參數(shù)
, 也就是說只能在函數(shù)內(nèi)部
使用 - 從Swift2.0開始會(huì)自動(dòng)將形參列表的第二個(gè)參數(shù)名稱作為標(biāo)簽, 也就是說
從第二個(gè)
參數(shù)開始, 參數(shù)的名稱既是內(nèi)部參數(shù)
又是外部參數(shù)
- 如何指定外部參數(shù)? 在方法中的參數(shù)的前面加上
外部參數(shù)名
- 默認(rèn)情況下所有形參都是
// 這里的yy就是外部參數(shù)
func sum3(num1:Int, yy num2:Int)
{
print("num1: \(num1), num2: \(num2)")
}
//sum3(100, num2: 200)
sum3(100, yy: 300)
- 默認(rèn)參數(shù)
- 如果指定了默認(rèn)值, 那么在調(diào)用方法的時(shí)候就
可以不用
傳遞數(shù)據(jù), 如果不傳遞數(shù)據(jù)系統(tǒng)就會(huì)使用默認(rèn)值, 如果傳遞了就會(huì)使用傳遞的值 - 在其它語言里面, 默認(rèn)值一般情況只能是最后一個(gè)參數(shù), 但是Swift可以寫在任何位置
- 構(gòu)造方法中麻诀,不能設(shè)置默認(rèn)參數(shù)
- 如果指定了默認(rèn)值, 那么在調(diào)用方法的時(shí)候就
func joinSting(str1: String, str2: String = "是", str3: String) -> String
{
return str1 + str2 + str3
}
joinSting("tym", str2: "不是", str3: "帥哥")
joinSting("tym", str3: "帥哥")
- 常量參數(shù)痕寓、變量參數(shù)以及inout參數(shù)
-
默認(rèn)
情況下所有形參都是常量
參數(shù), 不能在函數(shù)中修改形參的值 - 如果想在函數(shù)中修改形參的值, 那么必須把形參變?yōu)樽兞繀?shù)
- 和OC一樣, 在函數(shù)中修改形參的值
不會(huì)影響
到外面實(shí)參的值 - 如果想在函數(shù)中修改形參之后
影響
實(shí)參, 那么必須把形參變?yōu)閕nout參數(shù)
-
//func swap(a: Int, b: Int)
//{
// let temp = a
// a = b // 不能修改常量
// b = temp
//}
//func swap(var a: Int,var b: Int)
//{
// let temp = a
// a = b
// b = temp
// print("a = \(a), b = \(b)")
//}
//var a = 23
//var b = 24
//swap(&a, &b)
//
func swap1(inout a: Int,inout b: Int)
{
let temp = a
a = b
b = temp
print("a = \(a), b = \(b)")
}
var a1 = 23
var b1 = 24
print("a = \(a1), b = \(b1)")
swap1(&a1, b: &b1)
print("a = \(a1), b = \(b1)")
- 可變參數(shù)
- 只要參數(shù)是可變參數(shù), 就可以傳遞
一個(gè)
或多個(gè)
值 - 在其它語言中一般情況下可變參數(shù)只能是最后一個(gè)形參, 而Swift中可以寫在任意位置, 但是為了提高代碼的閱讀性, 還是建議寫在最后
- 只要參數(shù)是可變參數(shù), 就可以傳遞
func sum4(numbs:Int..., temp:Int , temp2: Int) -> Int
{
var sum = 0
for i in numbs
{
sum += i
}
return sum + temp + temp2
}
sum4(3, temp: 10, temp2: 20)
- 函數(shù)嵌套
- 將一個(gè)函數(shù)寫到另外一個(gè)函數(shù)的函數(shù)體中, 外面稱之為函數(shù)嵌套
- 1.被嵌套的函數(shù)只能在
父函數(shù)
內(nèi)部訪問 - 2.被嵌套的函數(shù)可以訪問
外部
的變量
- 1.被嵌套的函數(shù)只能在
- 應(yīng)用場(chǎng)景: 兩個(gè)函數(shù)之間依賴較強(qiáng), 或者一個(gè)函數(shù)就只給另外一個(gè)函數(shù)使用
- 例如: 對(duì)數(shù)組排序是一個(gè)函數(shù), 交換變量又是一個(gè)函數(shù), 他們就可以使用函數(shù)嵌套
- 將一個(gè)函數(shù)寫到另外一個(gè)函數(shù)的函數(shù)體中, 外面稱之為函數(shù)嵌套
let value = 23
func test(inout a:Int)
{
let number = 10
func demo()
{
print("\(number)", "\(a)", "\(value)")
}
demo()
}
var tes = 110
test(&tes)
構(gòu)造函數(shù)
- 當(dāng)重寫一個(gè)類的構(gòu)造方法時(shí),這個(gè)類會(huì)暗自幫我們調(diào)用super.init()
- 定義屬性蝇闭,直接寫在class里面
- 必須給這個(gè)類中所有的屬性進(jìn)行初始化
- 如果不能在創(chuàng)建對(duì)象時(shí)給這個(gè)類中所有的屬性進(jìn)行初始化呻率,那么這些屬性必須是可選的(?)
- 注意:
- 如果自定義一個(gè)類, 并且沒有重寫構(gòu)造方法, 那么系統(tǒng)會(huì)提供默認(rèn)的構(gòu)造方法
- 如果自定義一個(gè)類, 并且自定義了構(gòu)造方法, 并且沒有重寫原始的構(gòu)造方法,那么系統(tǒng)不會(huì)提供默認(rèn)的構(gòu)造方法
- 如果還需要原來的構(gòu)造方法呻引,需要重寫該構(gòu)造方法(盡管里面什么都不處理)
- Swift中要求在
創(chuàng)建
一個(gè)類時(shí)必須給這個(gè)類中所有的屬性
進(jìn)行初始化
- 如果不能在創(chuàng)建對(duì)象時(shí)給這個(gè)類中
所有的屬性
進(jìn)行初始化
, 那么這些屬性必須
是可選的
- 如果已經(jīng)在構(gòu)造方法中對(duì)所有的屬性進(jìn)行了初始化, 那么這些屬性就可以不是可選類型
- 在給某一個(gè)類指定屬性的數(shù)據(jù)類型時(shí), 如果該屬性是對(duì)象類型, 那么可以指定為可選類型
- 如果該屬性不是對(duì)象類型而是
基本數(shù)據(jù)
類型, 那么建議直接賦值為0
- 如果屬性是
基本數(shù)據(jù)
類型, 并且是可選
類型, 系統(tǒng)不會(huì)
自動(dòng)分配存儲(chǔ)
空間,在KVC的時(shí)候會(huì)出現(xiàn)問題
- 如果屬性是
- 如果不能在創(chuàng)建對(duì)象時(shí)給這個(gè)類中
var name: String?
var age: Int = 0
// 重寫構(gòu)造方法
override init() {
// 注意: 在構(gòu)造方法中必須先初始化本類再初始化父類
name = "tym"
age = 18
// 當(dāng)我們重寫一個(gè)類的構(gòu)造方法時(shí), 系統(tǒng)內(nèi)部會(huì)悄悄得幫我們調(diào)用super.init()
super.init()
}
// 自定義構(gòu)造方法
init(name: String, age: Int) {
self.name = name
self.age = age
// 以下這句代碼礼仗,能不寫就不寫
// super.init()
}
init(dict: [String: NSObject]) {
// 注意:Swift中如果想在構(gòu)造方法中使用KVC轉(zhuǎn)換模型, 必須先調(diào)用 super.init()
// 調(diào)用 super.init()的目的主要是為了給對(duì)象分配存儲(chǔ)空間
super.init()
setValuesForKeysWithDictionary(dict)
}
// Swift中打印對(duì)象,會(huì)調(diào)用以下屬性,重寫此屬性逻悠,方便測(cè)試
override var description: String {
// return "name:\(name), age:\(age)"
let keys = ["name","age"]
let dict = dictionaryWithValuesForKeys(keys)
return "\(dict)"
}
setter元践、getter方法
- OC
- setXXX
- getXXX
- Swift
- willSet、didSet
- get
- 如果只是想重寫一個(gè)屬性的get方法蹂风,可以直接return
var name: String?
{
// 在Swift開發(fā)中用以下兩個(gè)方法代替OC中的重寫setter方法
willSet{
print("賦值之前的調(diào)用\(newValue)")
}
didSet{
print("賦值之后的調(diào)用\(oldValue)")
}
}
var age: Int
{
// 在Swift中如果只重寫了get方法, 那么該屬性就是一個(gè)只讀屬性readOnly
// 如果一個(gè)屬性只重寫了get方法, 我們也稱之為"計(jì)算型屬性", 計(jì)算型屬性是不具備存儲(chǔ)能力的
// get{
// return 110
// }
// 如果只是想重寫一個(gè)屬性的get方法, 那么可以簡寫
return 120
}
閉包
- OC
- block類似于匿名函數(shù)卢厂,用于封裝代碼塊,在特定的時(shí)候執(zhí)行一些耗時(shí)操作
- 類型格式:
返回類型 (^block名字)(參數(shù)列表)
- 值格式: ^(形參列表){
需要執(zhí)行的代碼
}
<returnType>(^<blockName>)(<parameterTypes>) = ^(<parameters>) {
<statements>
};
```objc
@implementation ViewController
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[self loadData:^{
NSLog(@"刷新UI");
}];
}
-(void)loadData:(void (^)())finishBlock {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSLog(@"%@",[NSThread currentThread]);
NSLog(@"加載數(shù)據(jù)");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"%@",[NSThread currentThread]);
finishBlock();
});
});
}
@end
- Swift
- 閉包是用于定義函數(shù)(Swift中函數(shù)就是閉包惠啄,閉包是一個(gè)特殊的函數(shù))慎恒,執(zhí)行一些耗時(shí)操作
- 類型格式:(形參列表)->返回值類型
- 值格式:
{
(形參列表)->返回類型
in
需要執(zhí)行的代碼
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
loadData ({ () -> () in
print("刷新UI")
})
}
func loadData(finish:()->()) {
dispatch_async(dispatch_get_global_queue(0, 0)) { () -> Void in
print(NSThread.currentThread())
print("更新數(shù)據(jù)")
dispatch_async(dispatch_get_main_queue(), { () -> Void in
print(NSThread.currentThread())
finish()
})
}
}
}
- 閉包的寫法
- 完整寫法
loadData ({ () -> () in
print("更新UI")
})
+ 如果閉包`沒有形參`, 那么in和in之前的代碼都可以省略
```objc
loadData ({
print("更新UI")
})
- 如果閉包是函數(shù)的
最后一個(gè)參數(shù)
, 那么閉包可以寫在函數(shù)()的后面
loadData ( ){ () -> () in
print("更新UI")
}
- 如果函數(shù)
只有一個(gè)閉包參數(shù)
, 那么函數(shù)的()可以省略
loadData {
print("更新UI")
}
- 閉包的循環(huán)引用問題
- OC
- __weak : 如果對(duì)象釋放, 會(huì)自動(dòng)設(shè)置為nil
- __unsafe_unretained: 如果對(duì)象釋放, 不會(huì)自動(dòng)設(shè)置為nil
__weak typeof(self) weakSelf = self
- Swift
- 對(duì)應(yīng)關(guān)系: _weak == weak , _unsafe_unretained == unowned
weak var weakSelf = self loadData { () -> () in print("刷新UI") weakSelf!.view.backgroundColor = UIColor.greenColor() }
// 不建議此方法,因?yàn)閺?qiáng)制解包了 loadData { [weak self] () -> () in print("刷新UI") self!.view.backgroundColor = UIColor.greenColor() }
- OC
// 因?yàn)閡nowned相當(dāng)于_unsafe_unretained撵渡,不會(huì)設(shè)置成nil,所有不用強(qiáng)制解包
loadData { [unowned self] () -> () in
print("刷新UI")
self.view.backgroundColor = UIColor.greenColor()
}
```
-
單例
- OC
@interface Dog : NSObject + (instancetype)sharedDog; @end @implemetion Dog +(instancetype)sharedDog { static Dog *_instance = nil; // onceToken默認(rèn)等于0, 只要執(zhí)行一次之后就不等于0了, 原理是通過判斷onceToken是否等于0決定是否需要執(zhí)行block static dispatch_once_t onceToken; NSLog(@"%ld",onceToken); dispatch_once(&onceToken, ^{ _instance = [[self alloc] init]; }); return _instance; }
- Swift
- 注意:在func前添加class標(biāo)記融柬,相當(dāng)于是類方法,不添加趋距,相當(dāng)于是對(duì)象方法
// 方法一 static var onceToken:dispatch_once_t = 0; static var _instance:Dog? class func sharedDog() -> Dog { print(onceToken) dispatch_once(&Dog.onceToken) { _instance = Dog() } return _instance! } // 方法二 // 因?yàn)槭浅A苛Q酰灾荒苜x值一次 static let _instance:Dog = Dog() class func sharedDog()->Dog { return _instance } // 方法三,強(qiáng)烈推薦的方法 // 而且蘋果有統(tǒng)一的命名規(guī)范, 但凡是單例統(tǒng)一是shareInstance static let shareInstance:Dog = Dog()
懶加載
- 延遲存儲(chǔ)屬性
- Swift語言中
所有
的存儲(chǔ)屬性
必須有初始值, 也就是當(dāng)構(gòu)造完一個(gè)對(duì)象后, 對(duì)象中所有的存儲(chǔ)屬性必須有初始值, 但是也有例外, 其中延遲存儲(chǔ)屬性可以將屬性的初始化推遲
到該屬性第一次被調(diào)用的時(shí)候
- Swift語言中
- 懶加載應(yīng)用場(chǎng)景:
- 1.有可能不會(huì)用到
- 2.依賴于其它值
- 格式:
- lazy var 變量: 類型 = { 創(chuàng)建變量代碼 }()
- 懶加載的寫法本質(zhì)上是定義并執(zhí)行一個(gè)閉包
lazy var demoView: UIView = {
let v = UIView(frame: CGRectMake(10, 10, 100, 100))
v.backgroundColor = UIColor.redColor() return v
}()
gurad
- ?蘋果公司意識(shí)到Swift編寫的代碼节腐,會(huì)不知不覺得多層嵌套外盯,然后代碼變得非常丑陋,所以在Swift2.0的時(shí)候翼雀,專門推出了一個(gè)條件語句guard
- gurad 專門守護(hù)安全的
- 格式:
guard 條件語句 else {
需要執(zhí)行的語句
return
}```
- 特點(diǎn):只有條件為假的時(shí)候饱苟,才會(huì)執(zhí)行else中的代碼,相對(duì)于if else,這個(gè)只有else
- 作用: 用于過濾數(shù)據(jù)
---
# private
- 在Swift中狼渊,添加一個(gè)屬性或者方法可以在其他項(xiàng)目中的文件訪問
- 為了封裝性箱熬,可以添加private在屬性或者方法或者類前,可以讓該屬性或者方法只能在`當(dāng)前`文件中訪問
- 注意:
+ 由于點(diǎn)擊事件是由NSRunLoop發(fā)起的狈邑,并不是當(dāng)前的類發(fā)起的城须,如果在點(diǎn)擊方法前添加private,那么NSRunLoop無法找到該方法米苹,會(huì)導(dǎo)致崩潰
+ OC是基于運(yùn)行時(shí)動(dòng)態(tài)派發(fā)事件的
+ Swift是編譯時(shí)就已經(jīng)確定了方法
---
# @objc
- 想給監(jiān)聽點(diǎn)擊事件的方法加上private糕伐,并且又想讓系統(tǒng)動(dòng)態(tài)派發(fā)時(shí)找到該方法,可以在該方法前加上@objc驱入,@objc就能讓這個(gè)方法支持動(dòng)態(tài)派發(fā)
```objc
@objc private func composeBtnClick()
{
}
便利構(gòu)造方法
- 在Swift開發(fā)中赤炒,如果想要快速創(chuàng)建一個(gè)對(duì)象氯析,那么可以提供一個(gè)便利構(gòu)造器(遍歷構(gòu)造方法)
- 在普通構(gòu)造方法前面加上一個(gè)
convenience
,那么這個(gè)構(gòu)造方法就是一個(gè)便利構(gòu)造方法 - 注意:
- 如果定義一個(gè)便利構(gòu)造器,那么
必須
在便利構(gòu)造方法中調(diào)用指定構(gòu)造方法
(沒有convenience單詞的構(gòu)造方法)
- 如果定義一個(gè)便利構(gòu)造器,那么
// 以下方式的確可以快速創(chuàng)建一個(gè)對(duì)象莺褒,但是Swift不是這種風(fēng)格
class func createBtn(image:String, backgroundImage:String)->UIButton
{
let btn = UIButton(type: UIButtonType.Custom)
btn.setImage(UIImage(named: image), forState: UIControlState.Normal)
btn.setImage(UIImage(named: image + "_highlighted"), forState: UIControlState.Highlighted)
btn.setBackgroundImage(UIImage(named: backgroundImage), forState: UIControlState.Normal)
btn.setBackgroundImage(UIImage(named: backgroundImage + "_highlighted"), forState: UIControlState.Highlighted)
btn.sizeToFit()
return btn
}
/*
定義便利構(gòu)造器步驟:
1.編寫一個(gè)構(gòu)造方法
2.在構(gòu)造方法前面加上 convenience
3.在構(gòu)造方法中調(diào)用當(dāng)前類的其他"非便利構(gòu)造器"初始化對(duì)象
*/
convenience init(imageName: String, backImageName: String)
{
self.init()
// 1.設(shè)置背景圖片
setBackgroundImage(UIImage(named: imageName), forState: UIControlState.Normal)
setBackgroundImage(UIImage(named: imageName + "highlighted"), forState: UIControlState.Highlighted)
// 2.設(shè)置普通圖片
setImage(UIImage(named:backImageName), forState: UIControlState.Normal)
setImage(UIImage(named: backImageName + "highlighted"), forState: UIControlState.Highlighted)
sizeToFit()
}