推薦一個學習網站:https://www.cnswift.orgphp
該網站是對Swift官方文檔的翻譯,但不是無腦翻譯,而是結合做者的開發經驗,在翻譯的基礎上,給出一些實用的建議。
常量與變量python
在Swift中規定,定義一個標識符的時候必須明確說明該標識符是常量仍是變量:swift
使用let來定義常量,定義以後不可修改;數組
使用var來定義變量,定義以後能夠修改。ruby
let a: Int = 2a = 3//會報錯,由於a是常量,不能夠修改 var b: Int = 6b = 8//正常運行,b是變量,能夠修改
基本數據類型bash
Swift中的基本數據類型包括:整型、浮點型、Bool型數據結構
整型架構
有符號整型app
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中,不一樣類型的數據是不能夠運算的,好比整型和浮點型就不能夠一塊進行運算:
若是想要運算,那麼就要將其中一種類型轉爲另外一種類型:
var c = 1var d = 1.1Double(c)+d
Swift中的類型推導
Swift是一種強類型語言,也就是說,在Swift中,任何一個變量或者常量都必須有明確的類型。
var d: Int = 8
若是在定義一個標識符的時候有直接進行賦值,那麼標識符後面 的類型能夠省略:
var d = 8
由於Swift有類型推導,會自動根據後面的賦值來決定前面的標識符的數據類型。
咱們能夠經過option+鼠標左鍵來查看變量的數據類型:
須要注意的是,若是一個變量的類型已經肯定了,那麼就不能夠再給變量賦其餘類型的值:
這裏的變量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的類型以下:
這個類型是根據賦的值倒推出來的。
上面的元組one中的元素從左到右一次表示:名字、性別、年齡、身高。人們乍一看,其實仍是不知道每一個元素分別表明的意思的,因此爲了便於理解,爲了可以見文知意,咱們還能夠這樣來定義元組:
//給元組中的元素加上名稱,以後能夠經過元素名稱來訪問元素 var one = (name:"Norman", gender:"male", age:30, height:178.5) print(one.name)
摁住option鍵單擊,發現變量one的類型以下:
元組中元素的訪問
//寫法一 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中的三目運算與OC中保持了一致的風格。
let a = 10;let b = 20; //打印較大值print(a > b ? a : b);
guard的使用
guard語句與if語句很是相似,可是與if語句不一樣的是,guard語句當條件爲false的時候纔會執行{}裏面的代碼。
guard語句必須帶有else語句,他的語法以下:
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 = 100 switch a {case ..<60: print("不及格")case 60..<80: print("合格")case 80..<90: print("良好")case 90...100: print("優秀")default: print("天才")} /** 一個case能夠判斷多個值,多個值以,隔開*/let b = 0 switch b {case 0,1: print("正常人")default: print("其餘")} /** fallthrough關鍵字進行穿透* 所謂的穿透是指,當這個case知足的時候,執行完這個case所對應的內容以後,* 不會跳出,而是接着執行緊挨着的下一個case所對應的內容*/let c = 0 switch c {case 0: fallthroughcase 1: print("正常人")default: print("其餘")} /** switch是支持多種數據類型的* 不但支持整型、區間,還支持浮點型、字符串等。*/let d = 10let e = 5var result = 0 let 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中已經被淘汰了,以下:
還有一種是for-in循環,以下:
for i in 0..<10 { print(i)}
關於for-in循環,有一個特殊的地方須要注意:若是在某個循環中不須要用到下標i,那麼使用下劃線來代替下標,以下所示:
for _ in 0..<10 { print("Swift")}
否則的話會有以下的警告⚠️:
while循環和repeat-while循環
//while循環(先判斷,再執行)var a = 0 while a < 10 { print(a) a+=1} //repeat-while循環(先執行一次,再判斷)var a = 0 repeat { print(a) a += 1} while a < 0
Swift中的repeat-while循環與OC中的do-while循環其實如出一轍,均可以保證至少執行一次。
字符串
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")) //true print(str.contains("A")) //false print(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 >數組和元組</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"] = 178 dict["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) }
字典的合併
前面講的字符串和數組,都是能夠直接使用加號+來進行合併的,可是這一點對於字典並不適用。字典是不能夠直接使用加號+來進行合併的。
字典應該使用以下方式來合併:
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推出了可選類型。
可選類型的取值有以下兩種:
定義可選類型
//寫法一:官方定義方式 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轉Double var a : Int = 6 var b : Double = Double(a) //Float轉Int var c : Float = 8.99 var d : Int = Int(c)
基礎類型與字符串轉換
//字符串插值能夠直接將基礎類型轉換成字符串 var age : Int = 6 var 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,年齡:28 personalInfo("norman", 24) // 姓名:norman,年齡:24
3,指針的傳遞
默認狀況下,函數的參數是值傳遞。若是想改變外面的變量,則須要傳遞變量的地址。
//交換值 func swapInt(a : inout Int, b : inout Int) { let temp = a a = b b = temp } var a = 6 var b = 8 print("a=(a), b=(b)") // a=6, b=8 swap(&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 = additionMethod mathMethod(2, 3) // 5 //給函數類型變量賦其餘值 mathMethod = multiplicationMethod mathMethod(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) // 7 printResult(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