Swift簡介
在學習Swift之前,我們先來了解下什么是Swift
Swift是Apple在2014年6月WWDC發布的全新編程語言,中文名和LOGO是”雨燕“
Swift之父是Chris Lattner,也是Clang編譯器的作者,LLVM專案的主要發起人
Swift版本
Swift歷時七年,從Swift 1.*更新到Swift 5.*,經歷了多次重大改變,ABI終于穩定
API(Application Programming Interface):應用程式編程介面
- 源代碼和庫之間的介面
ABI(Application Binary Interface):應用程式二進制介面
- 應用程式和作業系統之間的底層介面
- 涉及的內容有:目標檔案格式、資料型別的大小/布局/對齊,函式呼叫約定等
Swift是完全開源的,下載地址:https://github.com/apple/swift
Swift編譯原理
LLVM編譯器
LLVM編譯器一般分為前端和后端
- 前端:主要進行詞法分析,生成語法樹
- 后端:生成對應平臺的二進制代碼
編譯流程
我們知道OC的前端是通過Clang進行編譯的,Swift的前端是通過swiftc來編譯的
不同語言的前端可能不同,但最終都會通過編譯器的后端生成對應平臺的二進制代碼

整個編譯流程如下圖所示

- Swift Code:我們撰寫的Swift代碼
- Swift AST:Swift語法樹
- Raw Swift IL:Swift特有的中間代碼
- Canonical Swift IL:更簡潔的Swift特有的中間代碼
- LLVM IR:LLVM的中間代碼
- Assembly:匯編代碼
- Executable:二進制代碼
關于Swift編譯流程的詳細講解可以參考以下網址:https://swift.org/swift-compiler/#compiler-architecture
swiftc
我們打開終端,輸入swiftc -help,會列印出相關指令,這也說明了swiftc已經存在于Xcode中

我們可以在應用程式中找到Xcode,然后右鍵顯示包內容,通過該路徑找到swiftc
路徑:/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin


swiftc的基本操作演練
下面我們可以通過一些swiftc的一些基本操作來了解
1.我們先新建一個Swift的命令列專案


2.然后打開終端,cd到main.swift路徑

3.然后我們輸入swiftc -dump-ast main.swift,來查看下生成的語法樹

4.我們還可以輸入swiftc -emit-sil main.swift生成最簡潔的SIL代碼

5.我們還可以輸入swiftc -emit-ir main.swift生成LLVM IR中間代碼

6.我們還可以輸入swiftc -emit-assembly main.swift生成匯編代碼

Swift基礎語法
Swift中列印輸入:print("Hello World")
Swift中一句代碼是可以省略分號的,但是如果多句代碼寫在一行,需要用分號隔開
Swift不用撰寫main函式,會以全域范圍內的首句可執行代碼作為入口來執行
通過反匯編我們可以看到底層會執行main函式

常量和變數
常量:
1.用let定義常量,常量只能賦值一次
不用特意指明型別,編譯器會自動進行推斷
let a: Int = 10
let b = 20
2.它的值不要求在編譯程序中確定,但使用之前必須賦值一次
這樣寫確定了a的型別,之后再去賦值,也不會報錯
let a: Int
a = 10
用函式給常量賦值也可以,函式是在運行時才會確定值的,所以只要保證使用之前賦值了就行
func getNumber() -> Int {
return 10
}
let a: Int
a = getNumber()
如果沒有給a確定型別,也沒有一開始定義的時候賦值,就會像下面這樣報錯

變數:
1.用var定義變數
var b = 20
b = 30
2.常量、變數在初始化之前,都不能使用

注釋
1.Swift中有單行注釋和多行注釋
注釋之間嵌套也沒有問題
// 單行注釋
/*
多行注釋
/*
多行注釋
*/
/*
// 注釋嵌套
*/
2.Playground里的注釋支持Markup語法(同Markdown)
Markup語法只在Playground里有效,在專案中無效
//: # 一級標題
/*:
## 基礎語法
*/
可以通過Editor -> Show Raw Markup來預覽

預覽的效果如下

識別符號
1.識別符號(比如常量名、變數名、函式名)幾乎可以使用任何字符
let ?? = 5
var ?? = 10
func ??() {
}
識別符號不能以數字開頭,不能包含空白字符、制表符、箭頭等特殊字符

常見資料型別
常見型別
- 值型別
- 列舉(enum): Optional
- 結構體(struct): Bool、Double、Float、Int、Character、String、Array、Dictionary、Set
- 參考型別
- 類(class)
可以通過command+control進入到該型別的API中查看
例如Int型別

整數型別
整數型別:Int8、Int16、Int32、Int64、UInt8、UInt16、UInt32、UInt64
在32bit平臺,Int等于Int32;在64bit平臺,Int等于Int64
整數的最值:UInt8.max,Int16.min
一般情況下,都是直接使用Int即可
let a: Int8 = 5
浮點型別
Float:32位,精度只有6位
Double:64位,精度至少15位
浮點型不指明型別默認就是Double
let a: Float = 2.0
let b = 3.0
字面量
字面量就是指這個量本身,就是一個固定值的表示法
下面這些都是字面量
Bool布爾
一般用Bool型別來表示是否的判斷,是為true,否為false
let bool = true
字串、字符
字串的寫法
let string = "hello"
字符型別要寫上Character,否則會被認為是字串
字符可存盤ASCII字符、Unicode字符
let character: Character = "a"
整數
不同進制的表示法
- 二進制以
0b開頭 - 八進制以
0o開頭 - 十六進制以
0x開頭
let intDecimal = 17 // 十進制
let intBinary = 0b10001 // 二進制
let intOctal = 0o21 // 八進制
let intHexadecimal = 0x11 // 十六進制
浮點數
let doubleDecimal = 125.0 // 十進制
let doubleDecimal2 = 1.25e2 // 也是125.0的另一種寫法,表示1.25乘以10的二次方
let doubleDecimal3 = 0.0125
let doubleDecimal4 = 1.25e-2 // 也是0.0125的另一種寫法,表示1.25乘以10的負二次方
let doubleHexadecimal1 = 0xFp2 // 十六進制,意味著15*2^2(15乘以2的二次方),相當于十進制的60
let doubleHexadecimal2 = 0xFp-2 //十六進制,意味著15*2^-2(15乘以2的負二次方),相當于十進制的3.75
整數和浮點數可以添加額外的零或者下劃線來增強可讀性
let num = 10_0000
let price = 1_000.000_000_1
let decimal = 000123.456
陣列
let array = [1, 2, 3, 4]
字典
let dictionary = ["age" : 18,
"height" : 1.75]
型別轉換
整數轉換
let int1: UInt16 = 2_000
let int2: UInt8 = 1
let int3 = int1 + UInt16(int2)
整數、浮點數轉換
let int = 3
let double = 0.1415926
let pi = Double(int) + double
let intPi = Int(pi)
字面量可以直接相加,因為數字字面量本身沒有明確的型別
let result = 3 + 0.14159
元組(tuple)
元組是可以多種資料型別組合在一起
let http404Error = (404, "Not Found")
print("The status code is \(http404Error.0)")
// 可以分別把元組里的兩個值分別進行賦值
let (statusCode, statusMsg) = http404Error
print("The status code is \(statusCode)")
// 可以只給元組里的某一個值進行賦值
let (justTheStatusCode, _) = http404Error
// 可以在定義的時候給元組里面的值起名
let http200Status = (statusCode: 200, description: "ok")
print("The status code is \(http200Status.statusCode)")
流程控制
if-else
Swift里的if else后面的條件是可以省略小括號的,但大括號不可以省略
let age = 10
if age >= 22 {
print("Get married")
} else if age >= 18 {
print("Being a adult")
} else if age >= 7 {
print("Go to school")
} else {
print("Just a child")
}
if else后面的條件只能是Bool型別

while
var num = 5
while num > 0 {
print("num is \(num)")
// 列印了五次
}
repeat-while相當于C語言中的do-while
先執行一次,再判斷條件回圈
var num = -1
repeat {
print("num is \(num)")
// 列印了一次
} while num > 0
這里不用num--是因為Swift3開始,已經去掉了自增(++)、自減(--)運算子
for
1.閉區間運算子:a...b,相當于a <= 取值 <= b
// 第一種寫法
let names = ["Anna", "Alex", "Brian", "Jack"]
for i in 0...3 {
print(names[i])
}
// 第二種寫法
let range = 0...3
for i in range {
}
// 第三種寫法
let a = 1
let b = 3
for i in a...b {
}
回圈里的i默認是let,如需要更改加上var
for var i in 0...3 {
}
不需要值的時候用_來表示
for _ in 0...3 {
}
2.半開區間運算子:a..<b,相當于a <= 取值 < b
for i in 0..<3 {
}
3.單側區間:讓一個區間朝一個方向盡可能的遠
for i in ...3 {
}
for _ in 3... {
}
4.區間運算子還可以用在陣列上
let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names[0...3] {
print(name)
}
for name in names[2...] {
print(name)
}
for name in names[...2] {
print(name)
}
for name in names[..<2] {
print(name)
}
let range = ...5
range.contains(4)
5.區間的幾種型別
閉區間 ClosedRange<Int>
1...3
半開區間 Range<Int>
1..<3
單側區間 PartialRangeThrough<Int>
...3
6.字符、字串也能使用區間運算子,但默認不能用在for-in中
let stringRange1 = "cc"..."ff"
stringRange1.contains("cd")
let stringRange2 = "a"..."f"
stringRange2.contains("c")
let characterRange:ClosedRange<Character> = "\0"..."~"
characterRange.contains("G")
7.帶間隔的區間值
let hours = 10
let hourInterval = 2
// tickmark的取值,從4開始,累加2,不超過10
for tickmark in stride(from: 4, through: hours, by: hourInterval) {
print(tickmark)
// 4,6,8,10
}
switch
使用同C語言的switch,不同的是case、default后面不寫大括號{}
var number = 1
switch number {
case 1:
print("number is 1")
break
case 2:
print("number is 2")
break
default:
print("number is other")
break
}
默認不寫case,并不會貫穿到后面的條件
var number = 1
switch number {
case 1:
print("number is 1")
case 2:
print("number is 2")
default:
print("number is other")
}
使用fallthrough可以實作貫穿效果
var number = 1
switch number {
case 1:
print("number is 1")
fallthrough
case 2:
print("number is 2")
default:
print("number is other")
}
// 會同時列印number is 1,number is 2
switch必須要保證能處理所有情況
注意:像判斷number的值,要考慮到所有整數的條件,如果不要判斷全部情況,加上default就可以了

case、default后面至少要有一條陳述句
如果不想做任何事,加個break即可
var number = 1
switch number {
case 1:
print("number is 1")
case 2:
break
default:
break
}
如果能保證已處理所有情況,也可以不必使用default
enum Answer { case right, wrong }
let answer = Answer.right
switch answer {
case .right:
print("right")
case .wrong:
print("wrong")
}
switch也支持Character和String型別
let string = "Jack"
switch string {
case "Jack":
fallthrough
case "Rose":
print(string)
default:
break
}
switch可以同時判斷多個條件
let string = "Jack"
switch string {
case "Jack", "Rose":
print(string)
default:
break
}
let character: Character = "a"
switch character {
case "a", "A":
print(character)
default:
break
}
switch也支持區間匹配和元組匹配
let count = 62
switch count {
case 0:
print("none")
case 1..<5:
print("a few")
case 5..<12:
print("several")
case 12..<100:
print("dozens of")
default:
print("many")
}
可以使用下劃線忽略某個值
let point = (1, 1)
switch point: {
case (2, 2):
print("1")
case (_, 0):
print("2")
case (-2...2, 0...):
print("3")
}
值系結,必要時let也可以改成var
let point = (2, 0)
switch point: {
case (let x, 0):
print(x)
case (0, let y):
print("2")
case let (x, y):
print("3")
}
where
一般where用來結合條件陳述句進行過濾
let point = (1, -1)
switch point {
case let (x, y) where x == y:
print("on the line x == y")
case let (x, y) where x == -y:
print("on the line x == -y")
case let (x, y):
print("\(x), \(y) is just some arbitrary point")
}
for i in 0...5 where i == 3 {
print(i)
}
標簽陳述句
用outer來標識回圈跳出的條件
outer: for i in 1...4 {
for k in 1...4 {
if k == 3 {
continue outer
}
if i == 3 {
break outer
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/271192.html
標籤:iOS
下一篇:iOS-審核4.3入坑(已出坑)
