Swift 基礎語法

来源:http://www.cnblogs.com/evening015/archive/2016/04/02/5348515.html
-Advertisement-
Play Games

一、變數和常量 定義 let 定義常量,一經賦值不允許再修改 var 定義變數,賦值之後仍然可以修改 自動推導 Swift能夠根據右邊的代碼,推導出變數的準確類型 通常在開發時,不需要指定變數的類型 如果要指定變數,可以在變數名後使用:,然後跟上變數的類型 重要技巧:Option + Click 可 ...


一、變數和常量

定義

  • let 定義常量,一經賦值不允許再修改
  • var 定義變數,賦值之後仍然可以修改
//: # 常量
//: 定義常量並且直接設置數值
let x = 20
//: 常量數值一經設置,不能修改,以下代碼會報錯
// x = 30

//: 使用 `: 類型`,僅僅只定義類型,而沒有設置數值
let x1: Int
//: 常量有一次設置數值的機會,以下代碼沒有問題,因為 x1 還沒有被設置數值
x1 = 30
//: 一旦設置了數值之後,則不能再次修改,以下代碼會報錯,因為 x1 已經被設置了數值
// x1 = 50

//: # 變數
//: 變數設置數值之後,可以繼續修改數值
var y = 200
y = 300

自動推導

  • Swift能夠根據右邊的代碼,推導出變數的準確類型
  • 通常在開發時,不需要指定變數的類型
  • 如果要指定變數,可以在變數名後使用:,然後跟上變數的類型

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

沒有隱式轉換!!!

  • Swift 對數據類型要求異常嚴格
  • 任何時候,都不會做隱式轉換

如果要對不同類型的數據進行計算,必須要顯式的轉換

let x2 = 100
let y2 = 10.5

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

let & var 的選擇

  • 應該儘量先選擇常量,只有在必須修改時,才需要修改為 var
  • 在 Xcode 7.0 中,如果沒有修改變數,Xcode 會提示修改為 let

二、Optional 可選類型

  • Optional 是 Swift 的一大特色,也是 Swift 初學者最容易困惑的問題
  • 定義變數時,如果指定是可選的,表示該變數可以有一個指定類型的值,也可以是 nil
  • 定義變數時,在類型後面添加一個 ?,表示該變數是可選的
  • 變數可選項的預設值是 nil
  • 常量可選項沒有預設值,主要用於在構造函數中給常量設置初始數值
//: num 可以是一個整數,也可以是 nil,註意如果為 nil,不能參與計算
let num: Int? = 10
  • 如果 Optional 值是 nil,不允許參與計算
  • 只有解包(unwrap)後才能參與計算
  • 在變數後添加一個 !,可以強行解包

註意:必須要確保解包後的值不是 nil,否則會報錯

//: num 可以是一個整數,也可以是 nil,註意如果為 nil,不能參與計算
let num: Int? = 10

//: 如果 num 為 nil,使用 `!` 強行解包會報錯
let r1 = num! + 100

//: 使用以下判斷,當 num 為 nil 時,if 分支中的代碼不會執行
if let n = num {
    let r = n + 10
}

常見錯誤

unexpectedly found nil while unwrapping an Optional value

翻譯

在[解包]一個可選值時發現 nil

?? 運算符

  • ?? 運算符可以用於判斷 變數/常量 的數值是否是 nil,如果是則使用後面的值替代
  • 在使用 Swift 開發時,?? 能夠簡化代碼的編寫
let num: Int? = nil

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


三、控制流

if

  • Swift 中沒有 C 語言中的非零即真概念
  • 在邏輯判斷時必須顯示地指明具體的判斷條件 true / false
  • if 語句條件的 () 可以省略
  • 但是 {} 不能省略
let num = 200
if num < 10 {
    print("比 10 小")
} else if num > 100 {
    print("比 100 大")
} else {
    print("10 ~ 100 之間的數字")
}

三目運算

  • Swift 中的 三目 運算保持了和 OC 一致的風格
var a = 10
var b = 20
let c = a > b ? a : b
print(c)

適當地運用三目,能夠讓代碼寫得更加簡潔

可選類型判斷

  • 由於可選類型的內容可能為 nil,而一旦為 nil 則不允許參與計算
  • 因此在實際開發中,經常需要判斷可選類型的內容是否為 nil

單個可選類型判斷

let url = NSURL(string: "http://www.baidu.com")

//: 方法1: 強行解包 - 缺陷,如果 url 為空,運行時會崩潰
let request = NSURLRequest(URL: url!)

//: 方法2: 首先判斷 - 代碼中仍然需要使用 `!` 強行解包
if url != nil {
    let request = NSURLRequest(URL: url!)
}

//: 方法3: 使用 `if let`,這種方式,表明一旦進入 if 分支,u 就不在是可選類型
if let u = url where u.host == "www.baidu.com" {
    let request = NSURLRequest(URL: u)
}

可選類型條件判斷

//: 1> 初學 swift 一不小心就會讓 if 的嵌套層次很深,讓代碼變得很醜陋
if let u = url {
    if u.host == "www.baidu.com" {
        let request = NSURLRequest(URL: u)
    }
}

//: 2> 使用 where 關鍵字,
if let u = url where u.host == "www.baidu.com" {
    let request = NSURLRequest(URL: u)
}
  • 小結
    • if let 不能與使用 &&|| 等條件判斷
    • 如果要增加條件,可以使用 where 子句
    • 註意:where 子句沒有智能提示

多個可選類型判斷

//: 3> 可以使用 `,` 同時判斷多個可選類型是否為空
let oName: String? = "張三"
let oNo: Int? = 100

if let name = oName {
    if let no = oNo {
        print("姓名:" + name + " 學號: " + String(no))
    }
}

if let name = oName, let no = oNo {
    print("姓名:" + name + " 學號: " + String(no))
}

判斷之後對變數需要修改

let oName: String? = "張三"
let oNum: Int? = 18

if var name = oName, num = oNum {

    name = "李四"
    num = 1

    print(name, num)
}

guard

  • guard 是與 if let 相反的語法,Swift 2.0 推出的
let oName: String? = "張三"
let oNum: Int? = 18

guard let name = oName else {
    print("name 為空")
    return
}

guard let num = oNum else {
    print("num 為空")
    return
}

// 代碼執行至此,name & num 都是有值的
print(name)
print(num)
  • 在程式編寫時,條件檢測之後的代碼相對是比較複雜的
  • 使用 guard 的好處
    • 能夠判斷每一個值
    • 在真正的代碼邏輯部分,省略了一層嵌套

switch

  • switch 不再局限於整數
  • switch 可以針對任意數據類型進行判斷
  • 不再需要 break
  • 每一個 case後面必須有可以執行的語句
  • 要保證處理所有可能的情況,不然編譯器直接報錯,不處理的條件可以放在 default 分支中
  • 每一個 case 中定義的變數僅在當前 case 中有效,而 OC 中需要使用 {}
let score = "優"

switch score {
case "優":
    let name = "學生"
    print(name + "80~100分")
case "良": print("70~80分")
case "中": print("60~70分")
case "差": print("不及格")
default: break
}
  • switch 中同樣能夠賦值和使用 where 子句
let point = CGPoint(x: 10, y: 10)
switch point {
case let p where p.x == 0 && p.y == 0:
    print("中心點")
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("對角線")
default:
    print("其他")
}
  • 如果只希望進行條件判斷,賦值部分可以省略
switch score {
case _ where score > 80: print("優")
case _ where score > 60: print("及格")
default: print("其他")
}


四、for 迴圈

  • OC 風格的迴圈
var sum = 0
for var i = 0; i < 10; i++ {
    sum += i
}
print(sum)
  • for-in,0..<10 表示從0到9
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)
  • 省略下標
    • _ 能夠匹配任意類型
    • _ 表示忽略對應位置的值
for _ in 0...10 {
    print("hello")
}


五、字元串

在 Swift 中絕大多數的情況下,推薦使用 String 類型

  • String 是一個結構體,性能更高
    • String 目前具有了絕大多數 NSString 的功能
    • String 支持直接遍歷
  • NSString 是一個 OC 對象,性能略差
  • Swift 提供了 String 和 NSString 之間的無縫轉換

字元串演練

  • 遍歷字元串中的字元
for s in str.characters {
    print(s)
}
  • 字元串長度
// 返回以位元組為單位的字元串長度,一個中文占 3 個位元組
let len1 = str.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)
// 返回實際字元的個數
let len2 = str.characters.count
// 返回 utf8 編碼長度
let len3 = str.utf8.count
  • 字元串拼接
    • 直接在 "" 中使用 \(變數名) 的方式可以快速拼接字元串
let str1 = "Hello"
let str2 = "World"
let i = 32
str = "\(i) 個 " + str1 + " " + str2

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

  • 可選項的拼接
    • 如果變數是可選項,拼接的結果中會有 Optional
    • 為了應對強行解包存在的風險,蘋果提供了 ?? 操作符
    • ?? 操作符用於檢測可選項是否為 nil
      • 如果不是 nil,使用當前值
      • 如果是 nil,使用後面的值替代
let str1 = "Hello"
let str2 = "World"
let i: Int? = 32
str = "\(i ?? 0) 個 " + str1 + " " + str2
  • 格式化字元串
    • 在實際開發中,如果需要指定字元串格式,可以使用 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)

String & Range 的結合

  • 在 Swift 中,String 和 Range連用時,語法結構比較複雜
  • 如果不習慣 Swift 的語法,可以將字元串轉換成 NSString 再處理
let helloString = "我們一起飛"
(helloString as NSString).substringWithRange(NSMakeRange(2, 3))
  • 使用 Range 的寫法
let startIndex = helloString.startIndex.advancedBy(0)
let endIndex = helloString.endIndex.advancedBy(-1)

helloString.substringWithRange(startIndex..<endIndex)


六、集合

數組

  • 數組使用 [] 定義,這一點與 OC 相同
//: [Int]
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  • 遍歷
for num in numbers {
    print(num)
}
  • 通過下標獲取指定項內容
let num1 = numbers[0]
let num2 = numbers[1]
  • 可變&不可變
    • let 定義不可變數組
    • var 定義可變數組
let array = ["zhangsan", "lisi"]
//: 不能向不可變數組中追加內容
//array.append("wangwu")
var array1 = ["zhangsan", "lisi"]

//: 向可變數組中追加內容
array1.append("wangwu")
  • 數組的類型
    • 如果初始化時,所有內容類型一致,擇數組中保存的是該類型的內容
    • 如果初始化時,所有內容類型不一致,擇數組中保存的是 NSObject
//: array1 僅允許追加 String 類型的值
//array1.append(18)

var array2 = ["zhangsan", 18]
//: 在 Swift 中,數字可以直接添加到集合,不需要再轉換成 `NSNumber`
array2.append(100)
//: 在 Swift 中,如果將結構體對象添加到集合,仍然需要轉換成 `NSValue`
array2.append(NSValue(CGPoint: CGPoint(x: 10, y: 10)))
  • 數組的定義和實例化
    • 使用 : 可以只定義數組的類型
    • 實例化之前不允許添加值
    • 使用 [類型]() 可以實例化一個空的數組
var array3: [String]
//: 實例化之前不允許添加值
//array3.append("laowang")
//: 實例化一個空的數組
array3 = [String]()
array3.append("laowang")
  • 數組的合併
    • 必須是相同類型的數組才能夠合併
    • 開發中,通常數組中保存的對象類型都是一樣的!
array3 += array1

//: 必須是相同類型的數組才能夠合併,以下兩句代碼都是不允許的
//array3 += array2
//array2 += array3
  • 數組的刪除
//: 刪除指定位置的元素
array3.removeAtIndex(3)
//: 清空數組
array3.removeAll()
  • 記憶體分配
    • 如果向數組中追加元素,超過了容量,會直接在現有容量基礎上 * 2
var list = [Int]()

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

字典

  • 定義
    • 同樣使用 [] 定義字典
    • let 不可變字典
    • var 可變字典
    • [String : NSObject] 是最常用的字典類型
//: [String : NSObject] 是最常用的字典類型
var dict = ["name": "zhangsan", "age": 18]
  • 賦值
    • 賦值直接使用 dict[key] = value 格式
    • 如果 key 不存在,會設置新值
    • 如果 key 存在,會覆蓋現有值
//: * 如果 key 不存在,會設置新值
dict["title"] = "boss"
//: * 如果 key 存在,會覆蓋現有值
dict["name"] = "lisi"
dict
  • 遍歷
    • kv 可以隨便寫
    • 前面的是 key
    • 後面的是 value
//: 遍歷
for (k, v) in dict {
    print("\(k) ~~~ \(v)")
}
  • 合併字典
    • 如果 key 不存在,會建立新值,否則會覆蓋現有值
//: 合併字典
var dict1 = [String: NSObject]()
dict1["nickname"] = "大老虎"
dict1["age"] = 100

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

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1 #include <stdio.h> 2 #include <string.h> //字元串處理庫 3 4 char tracks[][80]={ 5 "I left my heart in Harvard Med School", 6 "Newwark,Newwark - a wonderfu ...
  • 沒有很多東西,就是為了自己方便,編寫啦一段代碼,用來一鍵開啟博客園主頁。 恢復內容結束 ...
  • ...
  • 作為一個菜鳥,剛開始用java連接sqlserver的時候,用的時間不短, 可以說解決了一個又出現一個,所以我覺得有必要把我的經驗分享給大家。 (因為我踩了大部分的坑) 第一個坑:載入驅動。java要連接資料庫就需要驅動,我們去網上下載一個 sqljdbc.jar就行了。下載後該怎麼做呢。 這個時候 ...
  • 這篇文章有點深度,可能需要一些Lucene或者全文檢索的背景。由於我也很久沒有看過Lucene了,有些地方理解的不對還請多多指正。 更多內容 "還請參考整理的ELK教程" 關於Term Vectors 額,對於這個專業辭彙,暫且就叫做詞條向量吧,因為實在想不出什麼標準的翻譯。說的土一點,也可以理解為 ...
  • 原創,未經允許,禁止轉載!!! 分析依據:先載入的不能直接調用後載入的,因為後載入的並不存在無法被使用 後載入的能直接使用先載入的,因為先載入的已存在可以被使用比如:靜態方法先於實例變數,所以靜態方法直接調用實例變數就不行,因為實例變數還不在記憶體中,如下列代碼: 以此為依據使用debug得到分析結論 ...
  • 重載*運算符為友元函數。 ...
  • Filter被稱為過濾器或者攔截器,基本功能就是對調用servler過程的攔截,在servlet進行響應和處理前後實現一些特殊功能。其實,Filter過濾器就是一個實現了javax.servlet.Filter介面的類,在javax.servlet.Filter介面中定義了3個方法: init(Fi ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...