Switf入门到精通上
# 01.Swift基础语法
# 目录介绍
- 1.1 变量和常量
- 1.1.1 变量与常量的定义
- 1.1.2 变量命名
- 1.2 基本数据类型
- 1.2.1 整数类型
- 1.2.2 浮点数
- 1.2.3 布尔值
- 1.2.4 特殊类型
- 1.2.5 类型别名
- 1.2.6 类型安全
- 1.2.7 类型推断
- 1.3 字符和字符串
- 1.3.1 字符使用
- 1.3.2 字符串
- 1.3.3 转义字符
- 1.4 集合类型
- 1.4.1 数组Array类型
- 1.4.2 集合Set类型
- 1.4.3 字典Dictionary类型
- 2.1 运算符
- 2.1.1 赋值运算符
- 2.1.2 算术运算符
- 2.1.3 逻辑运算符
- 2.1.4 比较运算符
- 2.1.5 条件运算符
- 2.2 特殊运算符
- 2.2.1 空合并运算符
- 2.2.2 区间运算符
- 2.3 循环结构
- 2.3.1 for-in循环结构
- 2.3.2 while循环结构
- 2.3.3 repeat-while条件循环
- 2.4 条件选择与多分支选择
- 2.4.1 if与if-else
- 2.4.2 switch-case多分支
- 2.5 流程跳转语句
- 2.5.1 continue跳出
- 2.5.2 break跳出
- 2.5.3 fallthrough语句
- 2.5.4 return返回
- 2.5.5 throw抛出异常
- 2.5.6 guard语句
- 3.1 函数基本应用
- 3.1.1 函数创建与调用
- 3.1.2 函数的参数名
- 3.1.3 参数的默认值
- 3.2 函数类型和嵌套
- 3.3 理解闭包结构
- 3.3.1 什么是闭包
- 3.3.2 闭包表达式
- 3.3.3 尾随闭包
- 3.3.4 闭包是引用类型
# 1.1 变量和常量
# 1.1.1 变量与常量的定义
Swift 是一种类型安全语言,即常量或者变量在声明的时候必须指定明确的类型。
在使用变量前,你需要使用 var 关键字声明它,如下所示:
var variableName = <initial value>
以下是一个 Swift 程序中变量声明的简单实例:
var varA = 42
print(varA)
var varB: Float
varB = 3.14159
print(varB)
2
3
4
5
6
# 1.1.2 变量命名
变量名可以由字母,数字和下划线组成。
变量名需要以字母或下划线开始。
Swift 是一个区分大小写的语言,所以字母大写与小写是不一样的。
# 1.2 基本数据类型
# 1.2.1 整数类型
Int ,一般来说,你不需要专门指定整数的长度。Swift 提供了一个特殊的整数类型Int,长度与当前平台的原生字长相同:
- 在32位平台上,Int和Int32长度相同。
- 在64位平台上,Int和Int64长度相同。
除非你需要特定长度的整数,一般来说使用Int就够了。这可以提高代码一致性和可复用性。即使是在32位平台上,Int可以存储的整数范围也可以达到-2,147,483,648~2,147,483,647,大多数时候这已经足够大了。
UInt ,Swift 也提供了一个特殊的无符号类型UInt,长度与当前平台的原生字长相同:
- 在32位平台上,UInt和UInt32长度相同。
- 在64位平台上,UInt和UInt64长度相同。
注意: 尽量不要使用UInt,除非你真的需要存储一个和当前平台原生字长相同的无符号整数。除了这种情况,最好使用Int,即使你要存储的值已知是非负的。统一使用Int可以提高代码的可复用性,避免不同类型数字之间的转换,并且匹配数字的类型推断。
整数类型需要注意以下几点:
在 32 位系统上, Int 和 Int32 长度相同。
在 64 位系统上, Int 和 Int64 长度相同。
在 32 位系统上, UInt 和 UInt32 长度相同。
在 64 位系统上, UInt 和 UInt64 长度相同。
Int8, Int16, Int32, Int64 分别表示 8 位, 16 位, 32 位, 和 64 位的有符号整数形式。
UInt8, UInt16, UInt32, UInt64 分别表示 8 位, 16 位, 32 位 和 64 位的无符号整数形式。
# 1.2.2 浮点数
浮点数是有小数部分的数字,比如 3.14159,0.1 和 -273.15。
浮点类型比整数类型表示的范围更大,可以存储比 Int 类型更大或者更小的数字。Swift 提供了两种有符号浮点数类型:
- Double 表示64位浮点数。当你需要存储很大或者很高精度的浮点数时请使用此类型。
- Float 表示32位浮点数。精度要求不高的话可以使用此类型。
注意: Double精确度很高,至少有15位数字,而 Float 最少只有6位数字。选择哪个类型取决于你的代码需要处理的值的范围。
# 1.2.3 布尔值
Swift 有一个基本的布尔(Boolean)类型,叫做 Bool。布尔值指逻辑上的值,因为它们只能是真或者假。Swift 有两个布尔常量,true 和 false。
# 1.2.5 类型别名
类型别名对当前的类型定义了另一个名字,类型别名通过使用 typealias 关键字来定义。语法格式如下:
typealias newname = type
现在,我们可以通过别名来定义变量:
import Cocoa
typealias Feet = Int
var distance: Feet = 100
print(distance)
2
3
4
5
# 1.2.6 类型安全
Swift 是一个类型安全(type safe)的语言。
由于 Swift 是类型安全的,所以它会在编译你的代码时进行类型检查(type checks),并把不匹配的类型标记为错误。这可以让你在开发的时候尽早发现并修复错误。
var varA = 42
varA = "This is hello"
print(varA)
2
3
以上程序,会在 Xcode 中报错:
error: cannot assign value of type 'String' to type 'Int'
varA = "This is hello"
2
意思为不能将 'String' 字符串赋值给 'Int' 变量。
# 1.2.7 类型推断
当你要处理不同类型的值时,类型检查可以帮你避免错误。然而,这并不是说你每次声明常量和变量的时候都需要显式指定类型。
如果你没有显式指定类型,Swift 会使用类型推断(type inference)来选择合适的类型。
// varA 会被推测为 Int 类型
var varA = 42
print(varA)
// varB 会被推测为 Double 类型
var varB = 3.14159
print(varB)
// varC 也会被推测为 Double 类型
var varC = 3 + 0.14159
print(varC)
2
3
4
5
6
7
8
9
10
11
# 1.3 字符和字符串
# 1.3.1 字符使用
Swift 的字符是一个单一的字符字符串字面量,数据类型为 Character。
以下实例列出了两个字符实例:
let char1: Character = "A"
let char2: Character = "B"
// Swift 中以下赋值会报错
let char: Character = "AB"
print("char1 的值为 \(char1)")
print("char2 的值为 \(char2)")
2
3
4
5
6
7
Swift 的 String 类型表示特定序列的 Character(字符) 类型值的集合。 每一个字符值代表一个 Unicode 字符。
for ch in "Runoob" {
print(ch)
}
2
3
# 1.3.2 字符串
你可以通过使用字符串字面量或 String 类的实例来创建一个字符串:
// 使用字符串字面量
var stringA = "Hello, World!"
print( stringA )
// String 实例化
var stringB = String("Hello, World!")
print( stringB )
2
3
4
5
6
7
你可以将一个字符串赋值给一个变量或常量,变量是可修改的,常量是不可修改的。
// stringA 可被修改
var stringA = "菜鸟教程:"
stringA += "http://www.runoob.com"
print( stringA )
// stringB 不能修改
let stringB = String("菜鸟教程:")
stringB += "http://www.runoob.com"
print( stringB )
2
3
4
5
6
7
8
9
以上程序执行输出结果会报错,因为 stringB 为常量是不能被修改的:
error: left side of mutating operator isn't mutable: 'stringB' is a 'let' constant
stringB += "http://www.runoob.com"
2
# 1.3.3 转义字符
Swift 语言和C 语言类似,除了一些常规的可见字符外,其中还提供了一些有特殊用途的转义 字符,可通过特殊的符号组合来表示特定的意义。
# 1.4 集合类型
在Swift 语言中一共提供了3种集合类型: Array (数组)、Set (集合)和Dictionary (字典)。
- Array 类型是一种有序集合,放入其中的数据都有一个编号,且编号从0开始依次递增。通过编号, 开发者可以找到Array 数组中对应的值。
- Set 是一组无序的数据,其中存入的数据没有编号,开发 者可以使用遍历的方法获取其中所有的数据。
- Dictionary 是一种键值映射结构,其中每存入一个值 都要对应一个特定的键,且键不能重复,开发者通过键可以直接获取到对应的值。
# 1.4.1 数组Array类型
Swift 数组会强制检测元素的类型,如果类型不同则会报错,Swift 数组应该遵循像Array<Element>这样的形式,其中Element是这个数组中唯一允许存在的数据类型。
如果创建一个数组,并赋值给一个变量,则创建的集合就是可以修改的。这意味着在创建数组后,可以通过添加、删除、修改的方式改变数组里的项目。如果将一个数组赋值给常量,数组就不可更改,并且数组的大小和内容都不可以修改。
数组的创建可以使用两种方式,一种是使 用 Array 的构造方法来创建,一种是使用中括号来快捷创建,示例如下:
//创建空数组
var arrayl = []
var array1 = [1,2,3]
var array2 = Array(arrayLiteral:1,2,3)
2
3
4
Swift 语言中Array 采用结构体来实现,对于大量重复元素的数组,开发者可以直接使用快捷 方法来创建,示例如下:
//创建有10个String 类型元素的数组,并且每个元素都为字符串"Hello"
var array3=[String](repeating:"Hello",count:10)
2
# 1.4.2 集合Set类型
Set 类型的集合不关注其中元素的顺序,但是其中的元素不可以重复,读者也可以将其理解为一个无序的集合。Set 集合在进行声明时必须指定其类型,或者对其进行赋初值, 使得编译器可以自行推断出Set 的类型。
var set1 : Set<Int> = [1,2,3];
var set2 = Set(arrayLiteral:1,2,3,4);
2
# 1.4.3 字典Dictionary类型
Swift 字典用来存储无序的相同类型数据的集合,Swift 字典会强制检测元素的类型,如果类型不同则会报错。
Swift 字典每个值(value)都关联唯一的键(key),键作为字典中的这个值数据的标识符。
和数组中的数据项不同,字典中的数据项并没有具体顺序。我们在需要通过标识符(键)访问数据的时候使用字典,这种方法很大程度上和我们在现实世界中使用字典查字义的方法一样。
Swift 字典的key没有类型限制可以是整型或字符串,但必须是唯一的。
如果创建一个字典,并赋值给一个变量,则创建的字典就是可以修改的。这意味着在创建字典后,可以通过添加、删除、修改的方式改变字典里的项目。如果将一个字典赋值给常量,字典就不可修改,并且字典的大小和内容都不可以修改。
以下是创建一个空字典,键的类型为 Int,值的类型为 String 的简单语法:
var someDict = [Int: String]()
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
2
对字典操作案例如下所示:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
//可以根据字典的索引来访问数组的元素
var someVar = someDict[1]
print( "key = 1 的值 \(someVar)" )
//可以使用 updateValue(forKey:) 增加或更新字典的内容。如果 key 不存在,则添加值,如果存在则修改 key 对应的值。
var oldVal = someDict.updateValue("One 新的值", forKey: 1)
someVar = someDict[1]
print( "key = 1 的值 \(someVar)" )
//移除 Key-Value 对
var removedValue = someDict.removeValue(forKey: 2)
2
3
4
5
6
7
8
9
10
# 2.1 运算符
# 2.1.1 赋值运算符
赋值运算符应该是在编程中出现频率最高的运算符之一,在对任何量值进行赋值时,都需要 使用到赋值运算符“=”。
需要注意,“=”在Swift 语言中是赋值运算符,并不是相等运算符,对 于一些编程初学者,很容易将相等运算符“==”与赋值运算符“=”混淆使用。
# 2.1.2 算术运算符
算术运算符用于进行一些基本的数学运算,例如加、减、乘、除等。
需要注意的是,Swift 语言从2.2版本之后删除了自增运算符“++”与自减运算符“--”,目前版本的Swift语言中不可 以再使用这两个运算符。
var A = 10
var B = 20
print("A + B 结果为:\(A + B)")
print("A - B 结果为:\(A - B)")
print("A * B 结果为:\(A * B)")
print("B / A 结果为:\(B / A)")
A += 1 // 类似 A++
print("A += 1 后 A 的值为 \(A)")
B -= 1 // 类似 B--
print("B -= 1 后 B 的值为 \(B)")
2
3
4
5
6
7
8
9
10
11
# 2.1.3 逻辑运算符
逻辑运算符进行逻辑运算操作。可以简单理解 为,逻辑运算即是生活中所定义的真与假。系统定义的基本逻辑运算符会返回一个Bool类型的逻 辑值,因此,基本逻辑运算符组成的逻辑表达式在 if 判断语句中会经常用到。
Swift 中支持的基本逻辑运算符有逻辑与运算符“&&”、逻辑或运算符 “Il” 、 逻辑非运算符 “!”三种。逻辑运算只在逻辑值 (Bool 类型值)之间进行,与、或、非三种运算中前两者为二元 运算符,需要有两个Bool 类型的操作数。非运算符为一元运算符,需要一个Bool 类型的操作数,
它们有如下特点:
- ●与:两个操作数都为真,结果才为真,有一个操作数为假则结果为假。
- ●或:两个操作数有一个为真则结果为真,两个操作数都为假则结果为假。
- ●非:操作数为真则结果为假,操作数为假则结果为真。
# 2.1.4 比较运算符
Swift 中的比较运算符用于两个操作数之间的比较运算,其会返回一个Bool 类型的逻辑值。
基本的比较运算符有等于比较运算符“==”、小于比较运算符“<”、大于比较运算符“>”、不等 于比较运算符“!=”、小于等于比较运算符“<=”以及大于等于比较运算符“>=”。
# 2.1.5 条件运算符
条件运算符(三目运算符)是一种三元运算符,其可以简便实现代码中的条件选择逻辑。
# 2.2 特殊运算符
# 2.2.1 空合并运算符
可选值类型(Optional) 是 Swift 语言的一个独特之处,空合并运算符就是针对可选类型而设计的运算符。
空合并运算符(nil coalescing operator)用于提供一个默认值,以防止可选值为nil。空合并运算符使用两个连续的问号(??)表示。
let optionalName: String? = nil
let username = optionalName ?? "Guest"
print(username) // 输出: "Guest"
2
3
在上面的示例中,optionalName是一个可选字符串,其值为nil。使用空合并运算符,我们为username提供了一个默认值"Guest",以防optionalName为nil。
如果optionalName的值不为nil,那么username将取optionalName的值;如果optionalName为nil,那么username将取默认值"Guest"。
# 2.2.2 区间运算符
# 2.3 循环结构
# 2.3.1 for-in循环结构
Swift 语言中的for-in 结构则强大很多,既可以进行无序的循环遍历,也可以进行有序的循环遍历。
# 2.3.2 while循环结构
# 2.3.3 repeat-while条件循环
# 2.4 条件选择与多分支选择
# 2.4.1 if与if-else
# 2.4.2 switch-case多分支
# 2.5 流程跳转语句
# 2.5.1 continue跳出
# 2.5.2 break跳出
# 2.5.3 fallthrough语句
# 2.5.4 return返回
# 2.5.5 throw抛出异常
# 2.5.6 guard语句
guard 是一种用于提前退出函数、方法或循环的语句。它用于检查条件是否为真,如果条件为假,则执行 else 分支中的代码来执行提前退出操作。
guard 语句的一般语法如下:
guard condition else {
// 条件为假时执行的代码
// 执行提前退出操作,例如返回、抛出异常等
}
2
3
4
以下是一个示例,展示了如何使用 guard 语句来验证输入参数是否满足要求:
func processInput(_ input: Int) {
guard input > 0 else {
print("输入参数必须大于0")
return // 提前退出函数
}
// 在这里继续处理输入参数
print("输入参数有效,继续处理...")
}
2
3
4
5
6
7
8
9
使用 guard 语句来检查输入参数 input 是否大于 0。如果条件为假,则打印一条错误消息并提前退出函数。如果条件为真,则继续执行后续的代码。
使用 guard 语句可以提高代码的可读性和可维护性,避免了深层嵌套的条件语句。
# 3.1 函数基本应用
在数学中,函数有3要素:定义域、对应关系和值域。
在编程中,抛开函数的实现,在声明 函数时也有3要素:参数、返回值和函数名。参数和返回值决定函数的类型。参数数量和类型完全相同,同时返回值类型也相同的函数为同类型函数。
# 3.1.1 函数创建与调用
# 3.3 理解闭包结构
# 3.3.1 什么是闭包
闭包(Closures)是自包含的功能代码块,可以在代码中使用或者用来作为参数传值。
Swift 中的闭包与 C 和 Objective-C 中的代码块(blocks)以及其他一些编程语言中的 匿名函数比较相似。
全局函数和嵌套函数其实就是特殊的闭包。
Swift中的闭包有很多优化的地方:
- 根据上下文推断参数和返回值类型
- 从单行表达式闭包中隐式返回(也就是闭包体只有一行代码,可以省略return)
- 可以使用简化参数名,如$0, $1(从0开始,表示第i个参数...)
- 提供了尾随闭包语法(Trailing closure syntax)
let studname = { print("Swift 闭包实例。") }
studname()
let divide = {(val1: Int, val2: Int) -> Int in
return val1 / val2
}
let result = divide(200, 20)
print (result)
2
3
4
5
6
7
8
# 3.3.2 闭包表达式
闭包表达式是一种利用简洁语法构建内联闭包的方式。 闭包表达式提供了一些语法优化,使得撰写闭包变得简单明了。
Swift 标准库提供了名为 sorted(by:) 的方法,会根据您提供的用于排序的闭包函数将已知类型数组中的值进行排序。
排序完成后,sorted(by:) 方法会返回一个与原数组大小相同,包含同类型元素且元素已正确排序的新数组。原数组不会被 sorted(by:) 方法修改。
//使用闭包排序
let names = ["AT", "AE", "D", "S", "BE"];
// 使用普通函数(或内嵌函数)提供排序功能,闭包函数类型需为(String, String) -> Bool。
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
var reversed = names.sorted(by: backwards)
print(reversed);
2
3
4
5
6
7
8
# 3.3.3 尾随闭包
尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。
func someFunctionThatTakesAClosure(closure: () -> Void) {
// 函数体部分
}
// 以下是不使用尾随闭包进行函数调用
someFunctionThatTakesAClosure({
// 闭包主体部分
})
// 以下是使用尾随闭包进行函数调用
someFunctionThatTakesAClosure() {
// 闭包主体部分
}
2
3
4
5
6
7
8
9
10
11
12
13
sort() 后的 { $0 > $1} 为尾随闭包。
let names = ["AT", "AE", "D", "S", "BE"]
//尾随闭包
var reversed = names.sorted() { $0 > $1 }
print(reversed)
2
3
4
# 3.3.4 闭包是引用类型
这是因为函数和闭包都是引用类型。
无论您将函数/闭包赋值给一个常量还是变量,您实际上都是将常量/变量的值设置为对应函数/闭包的引用。 上面的例子中,incrementByTen指向闭包的引用是一个常量,而并非闭包内容本身。
这也意味着如果您将闭包赋值给了两个不同的常量/变量,两个值都会指向同一个闭包:
func makeIncrementor(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementor() -> Int {
runningTotal += amount
return runningTotal
}
return incrementor
}
let incrementByTen = makeIncrementor(forIncrement: 10)
// 返回的值为10
incrementByTen()
// 返回的值为20
incrementByTen()
// 返回的值为30
incrementByTen()
// 返回的值为40
let alsoIncrementByTen = incrementByTen
print(alsoIncrementByTen())
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19