二、字符串和字符
1.意义
-
字符串是一系列字符的集合, Swift 中的 String 类型的实现却很快速和现代化。每一个字符串都是由编码无关的 Unicode 字符组成,并支持访问字符的多种 Unicode 表示形式.
-
Swift 的 String 类型与 Foundation NSString 类进行了无缝桥接。Foundation 还对 String 进行扩展使其可以访问 NSString 类型中定义的方法。这意味着调用那些 NSString 的方法,你无需进行任何类型转换。
2、字符串字面量
- 字符串字面量是由一对双引号包裹着的具有固定顺序的字符集
3、字符串字面量的特殊字符
-
转义字符 \0(空字符)、\(反斜线)、\t(水平制表符)、\n(换行符)、\r(回车符)、"(双引号)、'(单引号)。
-
Unicode 标量,写成 \u{n}(u 为小写),其中 n 为任意一到八位十六进制数且可用的 Unicode 位码。
4、字符串可变性
- 你可以通过将一个特定字符串分配给一个变量来对其进行修改,或者分配给一个常量来保证其不会被修改
- 在 Objective-C 和 Cocoa 中,需要通过选择两个不同的类(NSString 和 NSMutableString)来指定字符串是否可以被修改。
5、字符串是值类型
6、字符串插值
- 字符串插值是一种构建新字符串的方式,可以在其中包含常量、变量、字面量和表达式
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message 是 "3 times 2.5 is 7.5"
7、字符串索引
- 使用 startIndex 属性可以获取一个 String 的第一个 Character 的索引。使用 endIndex 属性可以获取最后一个 Character 的后一个位置的索引。因此,endIndex 属性不能作为一个字符串的有效下标。如果 String 是空串,startIndex 和 endIndex 是相等的。
三、集合类型
1、集合类型
- Swift 语言提供数组(Array)、集合(Set)和字典(Dictionary)三种基本的集合类型用来存储集合数据。数组是有序数据的集。集合是无序无重复数据的集。字典是无序的键值对的集。
2、数组
- 数组使用有序列表存储同一类型的多个值。相同的值可以多次出现在一个数组的不同位置中。
- 创建一个带有默认值的数组
var threeDoubles = Array(repeating: 0.0, count: 3)
// threeDoubles 是一种 [Double] 数组,等价于 [0.0, 0.0, 0.0]
-
用数组字面量构造数组
var shoppingList: [String] = ["Eggs", "Milk"]
// shoppingList 已经被构造并且拥有两个初始项。
3、集合(set)
- 集合用来存储相同类型并且没有确定顺序的值。当集合元素顺序不重要时或者希望确保每个元素只出现一次时可以使用集合而不是数组。
- 创建和构造一个空的集合
var letters = Set<Character>()
print("letters is of type Set<Character> with \(letters.count) items.")
// 打印“letters is of type Set<Character> with 0 items.”
- 用数组字面量创建集合
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
// favoriteGenres 被构造成含有三个初始值的集合
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]
- 基本集合操作
- 使用 intersection(_:) 方法根据两个集合的交集创建一个新的集合。
- 使用 symmetricDifference(_:) 方法根据两个集合不相交的值创建一个新的集合。
- 使用 union(_:) 方法根据两个集合的所有值创建一个新的集合。
- 使用 subtracting(_:) 方法根据不在另一个集合中的值创建一个新的集合。
let oddDigits: Set = [1, 3, 5, 7, 9]
let evenDigits: Set = [0, 2, 4, 6, 8]
let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]
oddDigits.union(evenDigits).sorted()
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
oddDigits.intersection(evenDigits).sorted()
// []
oddDigits.subtracting(singleDigitPrimeNumbers).sorted()
// [1, 9]
oddDigits.symmetricDifference(singleDigitPrimeNumbers).sorted()
// [1, 2, 9]
let houseAnimals: Set = ["🐶", "🐱"]
let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"]
let cityAnimals: Set = ["🐦", "🐭"]
houseAnimals.isSubset(of: farmAnimals)
// true
farmAnimals.isSuperset(of: houseAnimals)
// true
farmAnimals.isDisjoint(with: cityAnimals)
// true
4、字典
- 字典是一种无序的集合,它存储的是键值对之间的关系,其所有键的值需要是相同的类型,所有值的类型也需要相同。每个值(value)都关联唯一的键(key),键作为字典中这个值数据的标识符。和数组中的数据项不同,字典中的数据项并没有具体顺序。
- 用字典字面量创建字典
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
- 创建一个空字典
var namesOfIntegers = [Int: String]()
// namesOfIntegers 是一个空的 [Int: String] 字典
四、控制流
1、For-In 循环
let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
print("Hello, \(name)!")
}
// Hello, Anna!
// Hello, Alex!
// Hello, Brian!
// Hello, Jack!
//如果你不需要区间序列内每一项的值,你可以使用下划线(_)替代变量名来忽略这个值:
let base = 3
let power = 10
var answer = 1
for _ in 1...power {
answer *= base
}
print("\(base) to the power of \(power) is \(answer)")
// 输出“3 to the power of 10 is 59049”
2、While循环
-
while 循环,每次在循环开始时计算条件是否符合;
-
repeat-while 循环(类似oc中的do-while),每次在循环结束时计算条件是否符合。
3、条件语句
-
Swift 提供两种类型的条件语句:if 语句和 switch 语句。通常,当条件较为简单且可能的情况很少时,使用 if 语句。而 switch 语句更适用于条件较复杂、有更多排列组合的时候。并且 switch 在需要用到模式匹配(pattern-matching)的情况下会更有用。
-
值绑定(Value Bindings):case 分支允许将匹配的值声明为临时常量或变量,并且在 case 分支体内使用 —— 这种行为被称为值绑定(value binding),因为匹配的值在 case 分支体内,与临时的常量或变量绑定 let anotherPoint = (2, 0) switch anotherPoint { case (let x, 0): print("on the x-axis with an x value of (x)") case (0, let y): print("on the y-axis with a y value of (y)") case let (x, y): print("somewhere else at ((x), (y))") } // 输出“on the x-axis with an x value of 2”
//case 分支的模式可以使用 where 语句来判断额外的条件。 let yetAnotherPoint = (1, -1) switch yetAnotherPoint { case let (x, y) where x == y: print("(\(x), \(y)) is on the line x == y") case let (x, y) where x == -y: print("(\(x), \(y)) is on the line x == -y") case let (x, y): print("(\(x), \(y)) is just some arbitrary point") } // 输出“(1, -1) is on the line x == -y”
4、控制转移语句
- continue:告诉一个循环体立刻停止本次循环,重新开始下次循环
- break:立刻结束整个控制流的执行
- fallthrough:fallthrough 关键字不会检查它下一个将会落入执行的 case 中的匹配条件。fallthrough 简单地使代码继续连接到下一个 case 中的代码,这和 C 语言标准中的 switch 语句特性是一样的。
- return
- throw
5、提前退出
-
一个 guard 语句总是有一个 else 从句,如果条件不为真则执行 else 从句中的代码。 func greet(person: [String: String]) { guard let name = person["name"] else { return }
print("Hello \(name)!") guard let location = person["location"] else { print("I hope the weather is nice near you.") return } print("I hope the weather is nice in \(location).") } greet(person: ["name": "John"]) // 输出“Hello John!” // 输出“I hope the weather is nice near you.” greet(person: ["name": "Jane", "location": "Cupertino"]) // 输出“Hello Jane!” // 输出“I hope the weather is nice in Cupertino.”
五、函数
1、函数的定义与调用
- 当你定义一个函数时,你可以定义一个或多个有名字和类型的值,作为函数的输入,称为参数,也可以定义某种类型的值作为函数执行结束时的输出,称为返回类型。
- 每个函数有个函数名,用来描述函数执行的任务。要使用一个函数时,用函数名来“调用”这个函数,并传给它匹配的输入值(称作实参)。函数的实参必须与函数参数表里参数的顺序一致。
2、函数参数与返回值
- 无参数函数
- 多参数函数
- 无返回值函数
- 多重返回值函数
//作用是在一个 Int 类型的数组中找出最小值与最大值。
func minMax(array: [Int]) -> (min: Int, max: Int) {
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
}
- 可选元组返回类型
- 可选元组类型如 (Int, Int)? 与元组包含可选类型如 (Int?, Int?) 是不同的。可选的元组类型,整个元组是可选的,而不只是元组中的每个元素值。
- 隐式返回的函数
- 可以省略reture
3、函数参数标签和参数名称
- 每个函数参数都有一个参数标签(argument label)以及一个参数名称(parameter name)。参数标签在调用函数的时候使用;调用的时候需要将函数的参数标签写在对应的参数前面。参数名称在函数的实现中使用。默认情况下,函数参数使用参数名称来作为它们的参数标签。
func someFunction(firstParameterName: Int, secondParameterName: Int) {
// 在函数体内,firstParameterName 和 secondParameterName 代表参数中的第一个和第二个参数值
}
someFunction(firstParameterName: 1, secondParameterName: 2)
- 输入输出参数(inout)
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
let temporaryA = a
a = b
b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// 打印“someInt is now 107, and anotherInt is now 3”
4、函数类型
- 每个函数都有种特定的函数类型,函数的类型由函数的参数类型和返回类型组成。
- 在 Swift 中,使用函数类型就像使用其他类型一样。例如,你可以定义一个类型为函数的常量或变量,并将适当的函数赋值给它: var mathFunction: (Int, Int) -> Int = addTwoInts
- 函数类型作为参数类型
- 你可以用 (Int, Int) -> Int 这样的函数类型作为另一个函数的参数类型
func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) {
print("Result: \(mathFunction(a, b))")
}
printMathResult(addTwoInts, 3, 5)
// 打印“Result: 8”
- 函数类型作为返回类型
- 你可以用函数类型作为另一个函数的返回类型。你需要做的是在返回箭头(->)后写一个完整的函数类型
func stepForward(_ input: Int) -> Int {
return input + 1
}
func stepBackward(_ input: Int) -> Int {
return input - 1
}
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
return backward ? stepBackward : stepForward
}
var currentValue = 3
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero 现在指向 stepBackward() 函数。
print(moveNearerToZero(1))
//0
5、嵌套函数
- 把函数定义在别的函数体中,称作 嵌套函数(nested functions)
func chooseStepFunction(backward: Bool) -> (Int) -> Int {
func stepForward(input: Int) -> Int { return input + 1 }
func stepBackward(input: Int) -> Int { return input - 1 }
return backward ? stepBackward : stepForward
}
var currentValue = -4
let moveNearerToZero = chooseStepFunction(backward: currentValue > 0)
// moveNearerToZero now refers to the nested stepForward() function
while currentValue != 0 {
print("\(currentValue)... ")
currentValue = moveNearerToZero(currentValue)
}
print("zero!")
// -4...
// -3...
// -2...
// -1...
// zero!