常量與變數
在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中,不同型別的資料是不可以運算的,比如整型和浮點型就不可以一塊進行運算:
如果想要運算,那麼就要將其中一種型別轉為另一種型別:
var c = 1var d = 1.1Double(c)+d
Swift中的型別推導
Swift是一種強型別語言,也就是說,在Swift中,任何一個變數或者常量都必須有明確的型別。
如果在定義一個識別符號的時候有直接進行賦值,那麼識別符號後面 的型別可以省略:
因為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語句,他的語法如下:
- 當條件表示式為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中已經被淘汰了,如下:
還有一種是for-in迴圈,如下:
for i in 0..<10 { print(i)}
關於for-in迴圈,有一個特殊的地方需要注意:如果在某個迴圈中不需要用到下標i,那麼使用下劃線來代替下標,如下所示:
for _ in 0..<10 { print("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)}
字典的合併
前面講的字串和陣列,都是可以直接使用加號+來進行合併的,但是這一點對於字典並不適用。字典是不可以直接使用加號+來進行合併的。
字典應該使用如下方式來合併:
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轉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/,如需轉載,請註明出處,否則將追究法律責任。