Swift基礎(chǔ)語法

Swift基礎(chǔ)語法

一.變量和常量

1.定義

  • let 定義常量,一經(jīng)賦值不允許再修改
  • var 定義變量核无,賦值之后仍然可以修改
//: # 常量
//: 定義常量并且直接設(shè)置數(shù)值
let x = 20
//: 常量數(shù)值一經(jīng)設(shè)置团南,不能修改炼彪,以下代碼會(huì)報(bào)錯(cuò)
// x = 30

//: 使用 `: 類型`,僅僅只定義類型拷橘,而沒有設(shè)置數(shù)值
let x1: Int
//: 常量有一次設(shè)置數(shù)值的機(jī)會(huì)喜爷,以下代碼沒有問題,因?yàn)?x1 還沒有被設(shè)置數(shù)值
x1 = 30
//: 一旦設(shè)置了數(shù)值之后术幔,則不能再次修改诅挑,以下代碼會(huì)報(bào)錯(cuò)泛源,因?yàn)?x1 已經(jīng)被設(shè)置了數(shù)值
// x1 = 50

//: # 變量
//: 變量設(shè)置數(shù)值之后俩由,可以繼續(xù)修改數(shù)值
var y = 200
y = 300

2.自動(dòng)推導(dǎo)

  • Swift能夠根據(jù)右邊的代碼幻梯,推導(dǎo)出變量的準(zhǔn)確類型
  • 通常在開發(fā)時(shí)碘梢,不需要指定變量的類型
  • 如果要指定變量煞躬,可以在變量名后使用:逸邦,然后跟上變量的類型

重要技巧:Option + Click 可以查看變量的類型

image.png

3.沒有隱式轉(zhuǎn)換B萍酢G沤啤裹芝!

  • Swift 對(duì)數(shù)據(jù)類型要求異常嚴(yán)格
  • 任何時(shí)候嫂易,都不會(huì)做隱式轉(zhuǎn)換

如果要對(duì)不同類型的數(shù)據(jù)進(jìn)行計(jì)算掐禁,必須要顯式的轉(zhuǎn)換

let x2 = 100
let y2 = 10.5

let num1 = Double(x2) + y2
let num2 = x2 + Int(y2)

4.let & var 的選擇

  • 應(yīng)該盡量先選擇常量穆桂,只有在必須修改時(shí)灼芭,才需要修改為 var
  • 在 Xcode 中彼绷,如果沒有修改變量茴迁,Xcode 會(huì)提示修改為 let

二.Optional 可選類型

1.介紹

  • Optional 是 Swift 的一大特色,也是 Swift 初學(xué)者最容易困惑的問題
  • 定義變量時(shí)猜旬,如果指定是可選的倦卖,表示該變量可以有一個(gè)指定類型的值怕膛,也可以是 nil
  • 定義變量時(shí)褐捻,在類型后面添加一個(gè) ?,表示該變量是可選的
  • 變量可選項(xiàng)的默認(rèn)值是 nil
  • 常量可選項(xiàng)沒有默認(rèn)值景馁,主要用于在構(gòu)造函數(shù)中給常量設(shè)置初始數(shù)值
// Optional 可能有兩個(gè)值 (None / Some)
// 格式(1. 自動(dòng)推導(dǎo)):var 變量名: Optional = 值
let x: Optional = 20
// 格式(2. 使用泛型):var 變量名:Optional<類型> = 值
let y: Optional<Int> = 30
// 格式(3. 簡(jiǎn)化格式):var 變量名: 類型? = 值
let z: Int? = 10

// 可選值在參與計(jì)算前,必須`解包 unwarping`
// 只有`解包(unwrap)`后才能參與計(jì)算
// 在變量后添加一個(gè) `!`慕购,可以強(qiáng)行解包
// `?` 是用于定義的
// `!` 是用于解包的茬底,程序員要對(duì)每一個(gè) `!` 負(fù)責(zé)
print(x! + y! + z!)
  • 如果 Optional 值是 nil阱表,不允許參與計(jì)算
  • 只有解包(unwrap)后才能參與計(jì)算
  • 在變量后添加一個(gè) !最爬,可以強(qiáng)行解包

注意:必須要確保解包后的值不是 nil爱致,否則會(huì)報(bào)錯(cuò)

// 常量可選項(xiàng)必須要設(shè)置初始值
let x: Int? //= 20
x = nil

// 變量可選項(xiàng)默認(rèn)值是 nil
var y: Int? //= 10
y = 20

// unexpectedly found nil while unwrapping an Optional value
// 在對(duì)可選項(xiàng)解包時(shí)發(fā)現(xiàn) nil糠悯,會(huì)報(bào)錯(cuò)互艾!
if y == nil || x == nil {
    print("y 或 x 為 nil")
} else {
    print(x! + y!)
}

常見錯(cuò)誤

unexpectedly found nil while unwrapping an Optional value

翻譯

在對(duì)可選項(xiàng)[解包]時(shí)發(fā)現(xiàn) nil

2.?? 運(yùn)算符 (空合并運(yùn)算符)

  • ?? 運(yùn)算符可以用于判斷 變量/常量 的數(shù)值是否是 nil纫普,如果是則使用后面的值替代
  • 在使用 Swift 開發(fā)時(shí)昨稼,?? 能夠簡(jiǎn)化代碼的編寫
var num: Int?

let r1 = (num ?? 0) + 10
print(r1)

三.控制流

1.if

  • Swift 中沒有 C 語言中的非零即真概念
  • 在邏輯判斷時(shí)必須顯示地指明具體的判斷條件 true / false
  • if 語句條件的 () 可以省略
  • 但是 {} 不能省略
func demo1(num: Int) -> () {
    if num > 10 {
        print("大 \(num)")
    } else {
        print("小 \(num)")
    }
}

2.三目運(yùn)算

  • Swift 中的 三目 運(yùn)算保持了和 OC 一致的風(fēng)格

func demo2() -> () {
    var a = 10
    var b = 20
    let c = a > b ? a : b
    print(c)
}

適當(dāng)?shù)剡\(yùn)用三目悦昵,能夠讓代碼寫得更加簡(jiǎn)潔

3.可選項(xiàng)判斷

  • 由于可選項(xiàng)的內(nèi)容可能為 nil但指,而一旦為 nil 則不允許參與計(jì)算
  • 因此在實(shí)際開發(fā)中,經(jīng)常需要判斷可選項(xiàng)的內(nèi)容是否為 nil
  • 如果單純使用 if连躏,會(huì)讓代碼嵌套層次很深贞滨,讓代碼不宜閱讀和維護(hù)晓铆,為了解決這一問題,蘋果提供了以下三種方式
    • ??
    • if let / var
    • guard let / var else

4.if let / var

func demo3(name: String?, age: Int?) {

    // 方法1: 強(qiáng)行解包 - 一旦出現(xiàn) nil 值尚困,程序崩潰
    // print(name! + String(age!) + "歲")

    // 方法2:使用 if let 判斷
    // 使用 `if let`事甜,這種方式逻谦,表明一旦進(jìn)入 if 分支跨跨,n & a 就不在是可選項(xiàng)
    // n 和 a 的作用域僅在 `{}` 內(nèi)部
    // 可以使用 `,` 同時(shí)判斷多個(gè)可選項(xiàng)是否為空
    if let n = name, let a = age {
        print(n + String(a) + "歲")
    } else {
        print("姓名或者年齡為 nil")
    }

    // 方法3: 使用同名參數(shù)囱皿,避免給變量再次起名的煩惱
    if let name = name, let age = age {
        print(name + String(age) + "歲")
    }
}

5.guard

  • guard 是與 if let 相反的語法勇婴,Swift 2.0 推出的
func demo4(name: String?, age: Int?) {

    guard let name = name, let age = age else {

        print("姓名或者年齡為 nil")

        return
    }

    print(name + String(age) + "歲")
}
  • 在程序編寫時(shí),條件檢測(cè)之后的代碼相對(duì)是比較復(fù)雜的
  • 使用 guard 的好處
    • 能夠判斷每一個(gè)值
    • 在真正的代碼邏輯部分嘱腥,省略了一層嵌套

6.switch

  • switch 不再局限于整數(shù)
  • switch 可以針對(duì)任意數(shù)據(jù)類型進(jìn)行判斷
  • 不再需要 break
  • 每一個(gè) case后面必須有可以執(zhí)行的語句
  • 要保證處理所有可能的情況耕渴,不然編譯器直接報(bào)錯(cuò),不處理的條件可以放在 default 分支中
  • 每一個(gè) case 中定義的變量?jī)H在當(dāng)前 case 中有效齿兔,而 OC 中需要使用 {}
let score = "優(yōu)"

switch score {
case "優(yōu)":
    let name = "學(xué)生"
    print(name + "80~100分")
case "良": print("70~80分")
case "中": print("60~70分")
case "差": print("不及格")
default: break
}
  • switch 中能夠賦值和使用 where 關(guān)鍵字添加賦加條件
let point = CGPoint(x: 10, y: 10)
switch point {
case let p where p.x == 0 && p.y == 0:
    print("中心點(diǎn)")
case let p where p.x == 0:
    print("Y軸")
case let p where p.y == 0:
    print("X軸")
case let p where abs(p.x) == abs(p.y):
    print("對(duì)角線")
default:
    print("其他")
}
  • 如果只希望進(jìn)行條件判斷橱脸,賦值部分可以省略
switch score {
case _ where score > 80: print("優(yōu)")
case _ where score > 60: print("及格")
default: print("其他")
}

四.for 循環(huán)

基礎(chǔ)循環(huán)

  • Range 和開閉區(qū)間

  • _ 可以表示忽略

  • C 風(fēng)格的循環(huán) (Swift 2.2 中過時(shí),Swift 3.0中被舍棄)

var sum = 0
for var i = 0; i < 10; i++ {
    sum += I
}
print(sum)
  • for-in添诉,0..<10 表示 [0,10)
sum = 0
for i in 0..<10 {
    sum += I
}
print(sum)
  • 范圍 0...10 表示 [0,10]
sum = 0
for i in 0...10 {
    sum += I
}
print(sum)

注意:..<... 用于定義 Range 類型,左右都不要添加空格

格式: for 變量 in 范圍 { // 代碼 }

  • 省略下標(biāo)
    • _ 能夠匹配任意類型
    • _ 表示忽略對(duì)應(yīng)位置的值
for _ in 0...10 {
    print("hello")
}

五.字符串

1.字符串演練

遍歷字符串中的字符

for s in str.characters {
    print(s)
}

字符串長(zhǎng)度

let str = "hello world你好世界"

// 1. 返回指定編碼的字節(jié)長(zhǎng)度
print(str.lengthOfBytes(using: .utf8))

// 2. 返回字符個(gè)數(shù)
print(str.characters.count)

// 3. 將字符串轉(zhuǎn)換成 NSString
let ocStr = str as NSString
print(ocStr.length)

字符串拼接

  • 直接在 "" 中使用 \(變量名) 的方式可以快速拼接字符串
let str1 = "Hello"
let str2 = "World"
let i = 32
str = "\(i) 個(gè) " + str1 + " " + str2

我和我的小伙伴再也不要考慮 stringWithFormat 了 :D

  • 可選項(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
  • 格式化字符串
    • 在實(shí)際開發(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)

2.String & Range 的結(jié)合

  • 在 Swift 中,StringRange連用時(shí)花颗,語法結(jié)構(gòu)比較復(fù)雜
  • 如果不習(xí)慣 Swift 的語法捕传,可以將字符串轉(zhuǎn)換成 NSString 再處理
let helloString = "我們一起飛"
(helloString as NSString).substringWithRange(NSMakeRange(2, 3))
  • 使用 Range<Index> 的寫法

3.0

let startIndex = helloString.index(str.startIndex, offsetBy: 2)
let endIndex = helloString.index(str.endIndex, offsetBy: -2)

helloString.substring(with: startIndex..<endIndex)

4.0

let startIndex = helloString.index(str.startIndex, offsetBy: 2)
let endIndex = helloString.index(str.endIndex, offsetBy: -2)

helloString[startIndex..<endIndex]

六.集合

1.數(shù)組

  • 數(shù)組使用 [] 定義,這一點(diǎn)與 OC 相同
//: [Int]
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  • 遍歷
// 1> 使用下標(biāo)遍歷
for i in 0..<numbers.count {
    print(numbers[I])
}

print("---- 遍歷數(shù)組項(xiàng)")

// 2> 遍歷數(shù)組項(xiàng)
for e in numbers {
    print(e)
}

print("---- 遍歷數(shù)組項(xiàng)和索引")

// 3> 遍歷數(shù)組項(xiàng)和索引
for e in numbers.enumerated() {
    print("\(e.offset) \(e.element)")
}

print("---- 遍歷數(shù)組項(xiàng)和索引 2")

// 4> 遍歷數(shù)組項(xiàng)和索引 2
for (n, c) in numbers.enumerated() {
    print("\(n) \(c)")
}

print("---- 倒序遍歷數(shù)組")

// 5> 倒序遍歷數(shù)組
for s in numbers.reversed() {
    print(s)
}

print("---- 倒序遍歷數(shù)組內(nèi)容和下標(biāo)")
// 6> 倒序遍歷數(shù)組內(nèi)容和下標(biāo)
for (n, c) in numbers.enumerated().reversed() {
    print("\(n) \(c)")
}
  • 可變&不可變
    • 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] as [Any]
//: 在 Swift 中聂示,數(shù)字可以直接添加到集合,不需要再轉(zhuǎn)換成 `NSNumber`
array2.append(100)
  • 數(shù)組的定義和實(shí)例化
    • 使用 : 可以只定義數(shù)組的類型
    • 實(shí)例化之前不允許添加值
    • 使用 [類型]() 可以實(shí)例化一個(gè)空的數(shù)組
var array3: [String]
//: 實(shí)例化之前不允許添加值
//array3.append("laowang")
//: 實(shí)例化一個(gè)空的數(shù)組
array3 = [String]()
array3.append("laowang")
  • 數(shù)組的合并
    • 必須是相同類型的數(shù)組才能夠合并
    • 開發(fā)中条霜,通常數(shù)組中保存的對(duì)象類型都是一樣的催什!
array3 += array1

//: 必須是相同類型的數(shù)組才能夠合并涵亏,以下兩句代碼都是不允許的
//array3 += array2
//array2 += array3
  • 數(shù)組的刪除
//: 刪除指定位置的元素
array3.removeAtIndex(3)
//: 清空數(shù)組
array3.removeAll()
  • 內(nèi)存分配
    • 如果向數(shù)組中追加元素宰睡,超過了容量,系統(tǒng)會(huì)增加合適的容量
var list = [Int]()

for i in 0...16 {
    list.append(i)
    print("添加 \(i) 容量 \(list.capacity)")
}

2.字典

  • 定義
    • 同樣使用 [] 定義字典
    • let 不可變字典
    • var 可變字典
    • [String : Any] 是最常用的字典類型
//: [String : Any] 是最常用的字典類型
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"
  • 刪除一個(gè) KEY
// 刪除 key 如果不存在麸恍,什么也不會(huì)發(fā)生
dict.removeValue(forKey: "height")
print(dict)

// 另一種刪除方式
dict["title"] = nil
print(dict)
  • 遍歷
    • kv 可以隨便寫
    • 前面的是 key
    • 后面的是 value
//: 遍歷
for (k, v) in dict {
    print("\(k) ~~~ \(v)")
}
  • 合并字典
    • 如果 key 不存在搀矫,會(huì)建立新值抹沪,否則會(huì)覆蓋現(xiàn)有值
//: 合并字典
var dict1 = [String: Any]()
dict1["nickname"] = "大老虎"
dict1["age"] = 100

//: 如果 key 不存在,會(huì)建立新值瓤球,否則會(huì)覆蓋現(xiàn)有值
for (k, v) in dict1 {
    dict[k] = v
}
print(dict)

七.錯(cuò)誤處理

反序列化JSON數(shù)據(jù)

  • 網(wǎng)絡(luò)訪問代碼
/// Swift 4 中 字符串換行的寫法
let data = """
{
    "weatherinfo": {
        "city": "北京",
        "cityid": "101010100",
        "temp": "18",
        "WD": "東南風(fēng)",
        "WS": "1級(jí)",
        "SD": "17%",
        "WSE": "1",
        "time": "17:05",
        "isRadar": "1",
        "Radar": "JC_RADAR_AZ9010_JB",
        "njd": "暫無實(shí)況",
        "qy": "1011",
        "rain": "0"
    }
}
""".data(using: String.Encoding.utf8)!

  • JSON 反序列化
// 方式1:強(qiáng)try.加載失敗直接崩潰
let dict = try! JSONSerialization.jsonObject(with: data!, options: [])
print(dict)

// 方式2:可選try.反序列化失敗返回nil
let dict = try? JSONSerialization.jsonObject(with: data!, options: [])
print(dict)

// 方式3:默認(rèn)try.返回序列化失敗可以捕捉詳細(xì)信息
do {
    let dict = try JSONSerialization.jsonObject(with: data!, options: [])
    print(dict)
}catch {
    print(error)
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末融欧,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子卦羡,更是在濱河造成了極大的恐慌噪馏,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绿饵,死亡現(xiàn)場(chǎng)離奇詭異欠肾,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)拟赊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門刺桃,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人吸祟,你說我怎么就攤上這事虏肾±。” “怎么了?”我有些...
    開封第一講書人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵封豪,是天一觀的道長(zhǎng)谴轮。 經(jīng)常有香客問我,道長(zhǎng)吹埠,這世上最難降的妖魔是什么第步? 我笑而不...
    開封第一講書人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮缘琅,結(jié)果婚禮上粘都,老公的妹妹穿的比我還像新娘。我一直安慰自己刷袍,他們只是感情好翩隧,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著呻纹,像睡著了一般堆生。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上雷酪,一...
    開封第一講書人閱讀 51,462評(píng)論 1 302
  • 那天淑仆,我揣著相機(jī)與錄音,去河邊找鬼哥力。 笑死蔗怠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的吩跋。 我是一名探鬼主播寞射,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼锌钮!你這毒婦竟也來了桥温?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤轧粟,失蹤者是張志新(化名)和其女友劉穎策治,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體兰吟,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡通惫,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了混蔼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片履腋。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出遵湖,到底是詐尸還是另有隱情悔政,我是刑警寧澤,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布延旧,位于F島的核電站谋国,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏迁沫。R本人自食惡果不足惜芦瘾,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望集畅。 院中可真熱鬧近弟,春花似錦、人聲如沸挺智。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽赦颇。三九已至二鳄,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間沐扳,已是汗流浹背泥从。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工句占, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留沪摄,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓纱烘,卻偏偏與公主長(zhǎng)得像杨拐,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子擂啥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354