Swift基礎語法簡化版

SLPA發表於2020-12-09

常量與變數

在Swift中規定,定義一個識別符號的時候必須明確說明該識別符號是常量還是變數:

使用let來定義常量,定義之後不可修改;

使用var來定義變數,定義之後可以修改。

let a: Int = 2a = 3//會報錯,因為a是常量,不可以修改var b: Int = 6b = 8//正常執行,b是變數,可以修改

基本資料型別

Swift中的基本資料型別包括:整型、浮點型、Bool型

整型

有符號整型

Int8:有符號8位整型

Int16:有符號16位整型

Int32:有符號32位整型

Int64:有符號64位整型

Int:預設,和平臺相關,相當於OC中的NSInteger

無符號整型

UInt8:無符號8位整型

UInt16:無符號16位整型

UInt32:無符號32位整型

UInt64:無符號64位整型

UInt:預設,和平臺相關,相當於OC中的NSUInteger

浮點型

Float:32位浮點型

Double:64位浮點型(預設)

Bool型

true:真

false:假

基本資料型別的運算與OC是一樣的:

a+b//加a-b//減a*b//乘a/b//除a%b//取餘

a+b//加a-b//減a*b//乘a/b//除a%b//取餘但是需要注意的是,在Swift中,不同型別的資料是不可以運算的,比如整型和浮點型就不可以一塊進行運算:

Swift基礎語法簡化版

如果想要運算,那麼就要將其中一種型別轉為另一種型別:

var c = 1var d = 1.1Double(c)+d

Swift中的型別推導

Swift是一種強型別語言,也就是說,在Swift中,任何一個變數或者常量都必須有明確的型別。

var d: Int = 8

如果在定義一個識別符號的時候有直接進行賦值,那麼識別符號後面 的型別可以省略:

var d = 8

因為Swift有型別推導,會自動根據後面的賦值來決定前面的識別符號的資料型別。

我們可以透過option+滑鼠左鍵來檢視變數的資料型別:

Swift基礎語法簡化版

需要注意的是,如果一個變數的型別已經確定了,那麼就不可以再給變數賦其他型別的值:

Swift基礎語法簡化版

這裡的變數c已經是整型了,那麼就只能給其賦整型值,不可賦其他型別的值。

運算子

計算運算子

+、-、*、/、%

需要特別注意的是,計算運算子兩邊的資料型別必須為同一型別,如果型別不同,則編譯器會報錯。

賦值運算子

=、+=、-=、*=、/=、%=

需要特別注意的是,賦值運算子兩邊的資料型別必須為同一型別,如果型別不同,則編譯器會報錯。

比較運算子

、>=、<、<=、==、!=

需要特別注意的是,比較運算子兩邊的資料型別必須為同一型別,如果型別不同,則編譯器會報錯。

區間運算子

Swift特有的。

1...8   //閉區間運算子,表示從1到8(包括1和8)的所有值的區間1...    //閉區間運算子,表示從1往後無限延伸...8    //閉區間運算子,表示從8往前無限延伸1..<8   //半開區間運算子,表示從1到8(包括1,但是不包括8)的所有值的區間..<8    //半開區間運算子,表示從8往前(不包括8)無限延伸

元組

OC中沒有元組型別,元組是Swift中特有的一種資料結構。

元組用於定義一組資料,組成元組的資料可以稱為元素。

我們現在使用元組來描述一個人的資訊:

var one = ("Norman", "male", 30, 178.5)print(one.0)

然後摁住option鍵單擊,發現變數one的型別如下:

Swift基礎語法簡化版

這個型別是根據賦的值倒推出來的。

上面的元組one中的元素從左到右一次表示:名字、性別、年齡、身高。人們乍一看,其實還是不知道每個元素分別代表的意思的,所以為了便於理解,為了能夠見文知意,我們還可以這樣來定義元組:

//給元組中的元素加上名稱,之後可以透過元素名稱來訪問元素var one = (name:"Norman", gender:"male", age:30, height:178.5)print(one.name)

摁住option鍵單擊,發現變數one的型別如下:

Swift基礎語法簡化版

元組中元素的訪問

//寫法一let error = (404, "Not Found")//下標訪問print(error.0)print(error.1)//寫法二let error = (errorCode:404, errorInfo:"Not Found")//別名訪問print(error.errorCode)print(error.errorInfo)

邏輯分支

分支的介紹

所謂的分支語句,就是if/switch/三目運算子等判斷語句。

透過分支語句可以控制程式的執行流程。

if分支語句

Swift中的if語句和OC中的if語句還是有區別的:

區別1:Swift中判斷句可以不加小括號(),但是判斷之後的執行語句必須要用大括號{}括起來;OC中判斷語句必須加小括號(),如果判斷之後的執行語句只有一句話的話可以省略大括號{}。

let g = 8if g>0 {    print("正數")}

區別2:Swift的判斷句中必須要有明確的真假,必須要有明確的布林值,Swift中不再有非0即真的概念;OC中是非0即真、非空即真。

Swift基礎語法簡化版

三目運算子

Swift中的三目運算與OC中保持了一致的風格。

let a = 10;let b = 20;//列印較大值print(a > b ? a : b);

guard的使用

guard語句與if語句非常類似,但是與if語句不同的是, guard語句當條件為false的時候才會執行{}裡面的程式碼

guard語句必須帶有else語句,他的語法如下:

  • 當條件表示式為true的時候跳過else語句的內容,執行後面的語句組;
  • 當條件表示式為false的時候執行else語句中的內容,跳轉語句一般是 return、break、continue或者throw
guard 條件表示式 else {  //當條件表示式不成立的時候執行的語句  break}語句組

另外一個需要說明的點是,guard語句必須放在函式中。

func online(age : Int) -> Void {    guard age >= 18 else {        print("未成年人不能上網")        return    }    print("可以上網")}online(age: 17)

Switch-case語句

switch作為選擇語句中必不可少的語句也被加入到了Swift中。

首先看一個例子:

/** case區間*/let a = 100switch a {case ..<60:    print("不及格")case 60..<80:    print("合格")case 80..<90:    print("良好")case 90...100:    print("優秀")default:    print("天才")}/** 一個case可以判斷多個值,多個值以,隔開*/let b = 0switch b {case 0,1:    print("正常人")default:    print("其他")}/** fallthrough關鍵字進行穿透* 所謂的穿透是指,當這個case滿足的時候,執行完這個case所對應的內容之後,* 不會跳出,而是接著執行緊挨著的下一個case所對應的內容*/let c = 0switch c {case 0:    fallthroughcase 1:    print("正常人")default:    print("其他")}/** switch是支援多種資料型別的* 不但支援整型、區間,還支援浮點型、字串等。*/let d = 10let e = 5var result = 0let opration = "+"switch opration {case "+":    result = d + ecase "-":    result = d - ecase "*":    result = d * ecase "/":    result = d / edefault:    result = 0}

Swift中的case後面的語句塊執行完畢之後可以不跟break,因為預設會有break。

迴圈

在C/OC中,常見的迴圈有for/while/do-while;在Swift中,對應的迴圈有for/while/repeat-while。

For迴圈

for迴圈分為兩種,一種是傳統的C語言風格的for迴圈,如下:

for var i = 0; i < 10; i++ {    print(i)}

這種傳統寫法,在Swift3中已經被淘汰了,如下:

Swift基礎語法簡化版

還有一種是for-in迴圈,如下:

for i in 0..<10 {    print(i)}

關於for-in迴圈,有一個特殊的地方需要注意:如果在某個迴圈中不需要用到下標i,那麼使用下劃線來代替下標,如下所示:

for _ in 0..<10 {    print("Swift")}

不然的話會有如下的警告⚠️:

Swift基礎語法簡化版

while迴圈和repeat-while迴圈

//while迴圈(先判斷,再執行)var a = 0while a < 10 {    print(a)    a+=1}//repeat-while迴圈(先執行一次,再判斷)var a = 0repeat {    print(a)    a += 1} while a < 0

Swift中的repeat-while迴圈與OC中的do-while迴圈其實一模一樣,都可以保證至少執行一次。

字串

OC和Swift中的字串是有區別的:

  • 在OC中,字串型別是NSString;在Swift中,字串型別是String。
  • OC中定義字串是使用@"";Swift中定義字串是使用""。

字串的定義

//不可變字串let str1 = "不可變字串"//可變字串var str2 = "可變字串"str2 = "我變變變"//多行字串var str3 = """多行字串第一行第二行第三行第四行56"""

上面介紹了了幾種傳統的字串定義形式,接下來我們來聊聊Swift5.0之後新推出的 Raw String(原始字串)

Raw String 是使用  # 來包裹字串,其最大的特點就是:它 不會對反斜槓\進行特殊的轉義處理

當字串中含有雙引號或者反斜槓轉義符的時候,使用傳統的方式定義如下:

let var1 = "如果句子中有雙引號\"\"就會很尷尬"//輸出:如果句子中有雙引號""就會很尷尬let var2 = "如果句子中有跳脫字元\\就會很尷尬"//輸出:如果句子中有跳脫字元\就會很尷尬

使用Swift5.0新推出的RawString定義如下:

let var1 = #"如果句子中有雙引號""就會很尷尬"#let var2 = #"如果句子中有跳脫字元\就會很尷尬"#

如果字串是被#包裹,那麼 \ 是不需要轉義的

那如果字串中有#,那怎麼辦呢?答案是使用兩個井號##來包裹:

let var1 = ##"如果句子中有井號#"##//列印結果:如果句子中有井號#

字串的常用操作

//計算字串的長度let str = "12345678"print(str.count)print((str as NSString).length)//拼接兩個字串var str1 = "Norman" + "Lee"var str2 = str1.appending("666")//遍歷字串(字串可以看成是多個字元的集合)let str = "abcdefg"for char in str {
    print(char)}//字串中是否包含某子字串let str = "abcdefg"print(str.contains("abc")) //trueprint(str.contains("A")) //falseprint(str.contains("h")) //false//分割字串let str = "abc&def&ghi&jkl&mn"let desc = str.components(separatedBy: "&") // ["abc", "def", "ghi", "jkl", "mn"]for item in desc {
    print(item)}//字串替換let str = "abc&def&ghi&jkl&mn"let result = str.replacingOccurrences(of: "&", with: "---")print(result) // abc---def---ghi---jkl---mn

陣列

陣列是一堆 有序的由 相同型別的元素構成的 集合。

陣列中的元素是有序的, 可以重複出現

Swift用 Array表示陣列,它是一個 泛型集合

陣列的初始化

陣列分為 可變陣列和不可變陣列

//定義一個可變陣列var arrar1 : [String] = [String]() //此時定義的是一個空陣列//定義一個不可變陣列let array2 : [String] = ["Norman", "Lavie"]

宣告一個Array型別有如下兩種寫法,可以任選其一:

//語法糖var array1 : [String]var array2 : Array<String>

宣告的陣列需要進行初始化才能使用,陣列型別往往是在宣告的同時進行初始化的:

//定義的同時直接進行初始化var array1 = ["Norman", "Lavie"]//先定義,然後初始化var array2 : Array<String>array2 = ["Norman", "Lavie"]

注意區分<u style="box-sizing: border-box; list-style: inherit;"> 陣列和元組</u>。

陣列的基本操作

var array = ["Norman", "Lavie", "緒雨成瀾"]//獲取長度array.count // 3//判空array.isEmpty // false//尾部新增元素array.append("大魚") // ["Norman", "Lavie", "緒雨成瀾", "大魚"]//指定位置插入元素array.insert("Bruce", at: 1) // ["Norman", "Bruce", "Lavie", "緒雨成瀾", "大魚"]//刪除元素array.remove(at: 0)array.removeLast()array.removeFirst()//修改元素array[0] = "小李"//取值(直接透過下標索引取值)print(array[0])print(array[1])//倒序array.reverse()

陣列的遍歷

var array = ["Norman", "Lavie", "緒雨成瀾", "大魚"]//for-in遍歷下標for i in 0..<array.count {
    print(array[i])}//for-in遍歷元素for name in array {
    print(name)}//遍歷某區間內的元素for name in array[0...2] {
    [print(name)]}//元組方式的遍歷(如果既需要拿到索引又需要拿到元素,推薦使用該方式)for (index, name) in array.enumerated() {
    print(index)
    print(name)}

陣列的合併

var array1 = ["Norman", "Lavie"]
var array2 = ["緒雨成瀾", "大魚"]
array1 += array2
print(array1) // ["Norman", "Lavie", "緒雨成瀾", "大魚"]

雖然僅僅用一個加號就可以實現陣列的合併,但是一定要保證一點:要合併的兩個或者多個陣列的 元素型別必須要保持一致

字典

字典是由 鍵值對(key:value)組成的集合,它由兩部分集合構成:一個是鍵集合,一個是值集合。字典是透過訪問鍵來間接訪問值的,鍵集合中是不可以有重複元素的,而值集合中的元素是可以重複的。

字典中的元素是 無序的。

Swift中的字典型別是Dictionary,是一個 泛型集合

字典的初始化

在Swift中,使用let修飾的字典是不可變字典,使用var修飾的字典是可變字典:

//定義一個可變字典var dic1 : [String : Any] = [String : Any]()//定義一個不可變字典let dic2 : [String : Any] = ["name" : "Norman", "age" : 28]

在宣告一個字典的時候,有下面兩種方式,可以任選其一:

var dic : [String : Any]var dic : Dictionary<String, Any>

跟陣列一樣,宣告的字典也是需要初始化之後才能使用:

//宣告的同時進行初始化var dic1 : [String : Any] = [String : Any]()//先宣告,後初始化var dic : Dictionary<String, Any>dic = ["name" : "Norman", "age" : 28]

額外說一點,在 Swift中,任意型別是使用Any來表示的。

字典的基本操作

var dict : [String : Any] = ["name" : "Lavie", "age" : 18, "gender" : "male"]//長度print(dict.count)//判空print(dict.isEmpty)//新增元素dict["height"] = 178dict["weight"] = 65/*
 * 需要注意的是,上面新增元素的這種方式,如果Key值不存在,那麼就是新增元素;
 * 如果Key值存在,那麼就是修改元素
 *///刪除元素dict.removeValue(forKey: "age") // 刪除指定元素dict.removeAll() // 刪除所有元素//修改字典dict["name"] = "Norman" // 方式一dict.updateValue("大魚", forKey: "name") // 方式二//查詢字典print(dict["name"])

字典的遍歷

var dict : [String : Any] = ["name" : "Lavie", "age" : 18, "gender" : "male"]//遍歷字典中所有的Value值for value in dict.values {
    print(value)}//遍歷字典中所有的Key值for key in dict.keys {
    print(key)}//遍歷所有的鍵值對for (key, value) in dict {
    print(key)
    print(value)}

字典的合併

前面講的字串和陣列,都是可以直接使用加號+來進行合併的,但是這一點對於字典並不適用。字典是不可以直接使用加號+來進行合併的。

Swift基礎語法簡化版

字典應該使用如下方式來合併:

var dict1 : [String : Any] = ["name" : "Lavie", "age" : 18, "gender" : "male"]var dict2 : [String : Any] = ["height" : 178, "weight" : 65]for (key, value) in dict2 {    dict1[key] = value}print(dict1) // ["gender": "male", "age": 18, "weight": 65, "height": 178, "name": "Lavie"]

但是這種合併字典的方式需要特別注意,如果有Key重名,那麼該Key在原字典中所對應的Value值將被新字典中所對應的Value值覆蓋。

可選型

在OC中,如果一個變數暫時不使用,可以賦值為0(基本資料型別)或者賦值為nil(物件型別)。在OC中,nil就表示一個空指標,它並不作為一個特殊的型別。

在Swift中, nil是一個特殊的型別,它與Int、String一樣,都是一種型別。並且 Swift語言又是一種強型別語言,因此不能直接將nil賦值給其他型別的資料。

在開發中,碰到nil在所難免,因此Swift推出了可選型別。

可選型別的取值有如下兩種:

  • 無值的情況下——nil
  • 有值的情況下——正常取值

定義可選型別

//寫法一:官方定義方式var a : Optional<Int> = 6 // 有值a = nil // nil//寫法二:語法糖(直接在型別後面加問號?)var b : Int? = 8 // 有值b = nil // nil

可選型別的使用

給可選型別賦值:

// 定義可選型別var name : String? = nil//給可選型別賦值name = 123 // ❌錯誤寫法,可選型別也是有型別校驗的,這裡只能複製字串,賦值其他型別都會報錯name = "norman" // 正確// 列印結果print(name) // Optional("norman")  因為是可選型別,所以會帶Optional

取出可選型別的值(顯性解包):

// 定義可選型別var name : String? = "Norman"print(name) // Optional("norman")//取出可選型別的真實值//使用!強制解包(顯性解包)print(name!) // Norman//如果可選型別為nil,強制解包會出錯name = nil//print(name!) // 報錯:Unexpectedly found nil while unwrapping an Optional value//正確寫法應該先判空if name != nil {
    print(name!)}

取出可選型別的值(隱式解包):

Swift中有一個 if-let寫法,if-let就是專門用於做可選繫結(隱式解包)的,如下:

if let 常量 = 可選型 {    //處理常量}

這裡的【常量 = 可選型】語句的作用是:如果可選型的值不是nil,那麼就將可選型的真實值傳給常量,並且執行花括號{}裡面的語句;如果可選型的值是nil,那麼【常量 = 可選型】這個條件就不成立(因為不能直接給一個非可選型變數賦值為nil),那麼就不會走到花括號裡面的內容。

// 定義可選型別var name : String? = "Norman"/*
 *可選繫結(隱式解包)
 */if let nameString = name {
    print(nameString)}

強烈推薦使用可選繫結來對可選型進行隱式解包

型別轉換

基礎資料型別轉換

比如Double轉Int,Int轉Float等,只需要使用資料型別(待轉型別)即可:

//Int轉Doublevar a : Int = 6var b : Double = Double(a)//Float轉Intvar c : Float = 8.99var d : Int = Int(c)

基礎型別與字串轉換

//字串插值可以直接將基礎型別轉換成字串var age : Int = 6var str = "小明今年\(age)歲了"//字串轉成基本型別,必須要保證字串的內容是可以轉換的var string = "123"var d = Int(string)

函式

Swift中的函式,其實就相當於Objective-C中的方法。函式的格式如下:

func 函式名(引數,列表)  -> 返回值型別 {    程式碼塊    return 返回值}

有以下幾點說明:

1,func 是定義函式的關鍵字

2,引數列表中的多個引數之間,可以使用英文逗號 , 分割,也可以沒有引數

3,使用 -> 指向返回值型別

4,如果函式沒有返回值,則 -> 返回值型別 部分可以省略

常見的函式型別

沒有引數,沒有返回值:

//寫法一:官方標準寫法func drinkWater() -> Void {
    print("drink water 111")}//寫法二:如果沒有返回值,Void可以寫成()func drinkWater1() -> () {
    print("drink water 222")}//寫法三:如果沒有返回值,後面的內容可以都不寫func drinkWater2() {
    print("drink water 333")}//呼叫函式drinkWater()drinkWater1()drinkWater2()

有引數,沒有返回值:

func call(phoneNumber : String) {    print("加入iOS交流群\(phoneNumber)")}call(phoneNumber: "642363427")

沒有引數,有返回值:

func myName() -> String {    return "norman"}let name = myName()

有引數,有返回值:

func plus(a : Int, b : Int) -> Int {    return a + b;}let result = plus(a: 3, b: 3)

函式的使用注意

1,每一個函式的形式引數都包含形式引數標籤和形式引數名兩部分

  • 形式引數標籤用在呼叫函式的時候
  • 形式引數名用在函式的實現當中
  • 在呼叫函式的時候,每一個形式引數前邊都會有一個形式引數標籤
  • 預設情況下,形式引數使用它們的形式引數名作為形式引數標籤
  • 如果不想要形式引數標籤,可以在形式引數名稱前加上 _
//這裡的info1和info2就是形式引數標籤//name和age是形式引數名稱func personalInfo(info1 name : String, info2 age : Int) {
    //在函式的實現中使用形式引數名稱
    print("姓名:\(name),年齡:\(age)")}//在函式呼叫的時候使用形式引數標籤personalInfo(info1: "norman", info2: 23)//下面是預設寫法//此時,name和age既是形式引數標籤,也是形式引數名稱func personalInfo(name : String, age : Int) {
    //在函式內部實現的時候,name和age是形式引數名稱
    print("姓名:\(name),年齡:\(age)")}//在函式呼叫的時候,name和age是形式引數標籤personalInfo(name: "norman", age: 24)//如果不想要形式引數標籤,可以在形式引數名稱前面加 _func personalInfo(_ name : String, _ age : Int) {
    print("姓名:\(name),年齡:\(age)")}//在函式呼叫的時候,沒有形式引數標籤personalInfo("norman", 24)

2,可以給函式的引數設定預設值

//如果不想要形式引數標籤,可以在形式引數名稱前面加 _func personalInfo(_ name : String = "lavie", _ age : Int = 28) {
    print("姓名:\(name),年齡:\(age)")}personalInfo() // 姓名:lavie,年齡:28personalInfo("norman", 24) // 姓名:norman,年齡:24

3,指標的傳遞

預設情況下,函式的引數是值傳遞。如果想改變外面的變數,則需要傳遞變數的地址。

//交換值func swapInt(a : inout Int, b : inout Int) {
    let temp = a
    a = b
    b = temp}var a = 6var b = 8print("a=\(a), b=\(b)") // a=6, b=8swap(&a, &b) // 將地址傳遞進來print("a=\(a), b=\(b)") // a=8, b=6

函式的型別

我們之前介紹的陣列Array、字典Dictionary等,都是 值型別,而函式是 引用型別

每個函式都有屬於自己的型別,一個函式的型別是由該函式的 引數型別返回型別決定的。

有了函式型別以後,就可以把函式型別像Int、Array一樣來使用了。

下面的例子定義了additionMethod和multiplicationMethod兩個函式,這兩個函式都傳入了兩個Int型別的引數,返回一個Int型別值,因此這兩個函式的型別都是(Int, Int) -> Int

func additionMethod(a : Int, b : Int) -> Int {    return a + b;}func multiplicationMethod(a : Int, b : Int) -> Int {    return a * b;}

接下來我們來看一下函式的簡單賦值:

//初始化一個函式型別變數,並賦初始值var mathMethod = additionMethodmathMethod(2, 3) // 5//給函式型別變數賦其他值mathMethod = multiplicationMethodmathMethod(2, 3) // 6

函式也可以作為一個函式的引數:

func additionMethod(a : Int, b : Int) -> Int {
    return a + b;}func multiplicationMethod(a : Int, b : Int) -> Int {
    return a * b;}//函式作為引數func printResult(a : Int, b : Int, mathMethod : (Int, Int) -> Int) {
    print(mathMethod(a, b))}printResult(a: 3, b: 4, mathMethod: additionMethod) // 7printResult(a: 3, b: 4, mathMethod: multiplicationMethod) // 12

函式還可以作為一個函式的返回值:

func additionMethod(a : Int, b : Int) -> Int {
    return a + b;}func multiplicationMethod(a : Int, b : Int) -> Int {
    return a * b;}//函式作為返回值func mathMethod(a : Int) -> (Int, Int)->Int {
    if a > 10 {
        return additionMethod    }
    return multiplicationMethod}var resultMethod = mathMethod(a: 11)resultMethod(6, 8) // 14

推薦文章


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69990324/viewspace-2740642/,如需轉載,請註明出處,否則將追究法律責任。