元组
- 定义: 可以将多个不同类型的值合成单个复合值。(可以是任意类型的)
- 使用:
-
可以将内容分为常量或变量进行常规访问:
let https = (404,"Not Found") let (statusCode, statusMessage) = https print("The status code is \(statusCode)") //输出:The status code is 404
-
如只需某些元组的值,可以用“_”来忽略元组的部分值
let (value , _ ) = https print("The status code is \(value)") //输出:The status code is 404
-
使用从0开始索引访问元组各个元素值或给元组各个元素命名来访问
let examples = (a:200,b:"OK") print("The value is \(examples.0)") //输出:The value is 200 print("The value is \(examples.a)") //输出:The value is 200
-
适用:
- 作为函数的返回值特别有用
- 互换值:(a,b)= (b,a) 等
-
可选类型
- 定义:可能不存在值的数据类型。两种可能:要么是有一个值,你可以解开可选的访问值,或者是没有价值可言,为nil。
- 注意: Object-C和swift中的nil不同:OC中是一个指向不存在对象的指针,只适用于对象(引用)类型,不适用与值类型。swift中nil不是一个指针,它是没有某种类型的值,任何类型的可选项都可以设置为nil,而不仅仅是对象类型。
- 使用:
如果你的代码中的常量或者变量在某些情况下缺少值时使用,则始终将其声明为适当类型的可选值。(可选类型默认值:nil)
-
一般展开可选类型的写法
if 可选类型名 != nil { print("It must have a value \(可选类型名!) ") }
-
安全展开可选类型的写法(可选绑定:来确定可选项是否包含值,如果是,则将值用作临时常量或变量。否则走else)
if let newValue = 可选类型名 { print("It must have a value \(newValue) ") } 重点:可以包含多个(let newValue = 可选类型名),中间用“,”隔开,只要其中一个为nil则整个表达式都为否。
可以使用感叹号来访问其基础值(注:一旦使用!访问,必须保证一定存在值,否则将error)
??:进行解包,如果包含值则返回本身,否则返回默认值。a ?? b <==> a != nil ? a! : b
- 隐式解析可选类型
-
定义后缀
!
作为标准库中命名类型Optional
的语法糖,来实现自动解包的功能var implicitlyUnwrappedString: String! var explicitlyUnwrappedString: Optional
-
注意:由于隐式解包修改了包含器类型的声明语义,嵌套在元组类型或泛型的可选类型(比如字典元素类型或数组元素类型),不能被标记为隐式解包。
let tupleOfImplicitlyUnwrappedElements: (Int!, Int!) // 错误 let implicitlyUnwrappedTuple: (Int, Int)! // 正确 let arrayOfImplicitlyUnwrappedElements: [Int!] // 错误 let implicitlyUnwrappedArray: [Int]! // 正确
-
元类型
- 定义: 元类型是指类型的类型,包括类类型、结构体类型、枚举类型和协议类型。
- 获取元类型:类、结构体或枚举类型的元类型是相应的类型名紧跟
.Type
。协议类型的元类型——并不是运行时符合该协议的具体类型——而是该协议名字紧跟.Protocol
。比如,类SomeClass
的元类型就是SomeClass.Type
,协议SomeProtocol
的元类型就是SomeProtocal.Protocol
。 - 类型名.self来获取类型。也可以使用
type(of:)
来获取该实例在运行期的类型。
使用goard的正确姿势
-
可以用goard:在验证入口条件时
func refreshData() { let session = Int("12") goard let value = session else {reture} print("\(session!)") } 好处: 1.一眼看出,这个条件检查并不是函数本身的功用,而是函数执行的先决条件。 2.如果有人不小心将提前退出的语句从 else 表达式中移除了,编译器会及时告诉你这个错误。
使用场景:方法中存在非常长的执行路径,在最终结果得到之前,中间会有多个需要被满足的条件,这些条件都应该为真,否则应该直接 return 或者抛出异常。(这些条件可以用guard抛出)
-
可以用 guard:在可选值解包时(拍扁 if let..else 金字塔):使用 guard 的方式来解包可选值是非常推荐的。if let 的方式需要在大括号内使用解包之后的值,而 guard 语句将解包之后的值添加到了之后的作用域之中——所以你可以在使用 guard 解包之后直接使用它,不用包裹在大括号内。
guard let id = json["id"] as? Int, let name = json["name"] as? String, let userId = json["user_id"] as? Int, let position = json["pos"] as? Double else { throw ParsingError.MissingData } return Task(id: id, name: name, userId: userId, position: position)
错误处理
-
可以使用值得存在或不存在来传达函数的成功或失败,错误处理允许您确定故障的根本原因,如有必要,将错误传播到程序的一部分。
如:throws关键字来引发错误 func canThrowAnError() throws { } 使用:当调用此函数时,需要使用如下方式,并加上try关键字,catch可以是多个 do { try canThrowAnError() } catch { }
断言和前提条件
- 定义:断言和前提条件是在运行时发生的检查。在执行任何其他代码之前,您可以使用它们确保满足基本条件。如果断言或前提条件中的布尔条件评估为true,则代码执行情况依然如常。如果条件求值false,程序的当前状态无效; 代码执行结束,您的应用程序已终止
- 使用:
- assert(age >= 0, "A person's age can't be less than zero."): 当条件为false就会抛出error错误信息,
- precondition(index > 0, "Index must be greater than zero.") :同上
- assertionFailure("A person's age can't be less than zero."):当已经检查了某条件时,可以直接吃用此方法抛出错误
- preconditionFailure("A person's age can't be less than zero."):同上
基本运算符
a...b :全封闭区间,相当于[a,b];
a..
-
单面范围: [a...],[...b],[..
for name in names[2...] { //从下标2开始到最后 print(name) } for name in names[...2] { //从下标0到下标2的所有元素 print(name) }
字符串与字符
-
如果需要一个跨多行的字符串,请使用多行字符串文字 - 由三个双引号包围的一系列字符。
如:let example = """ The first row The sencond Row ... """
-
使用”+“来拼接两个字符串。
//实例 let badStart = """ one two """ let end = """ three """ print(badStart + end) // Prints two lines: // one // twothree let goodStart = """ one two """ print(goodStart + end) // Prints three lines: // one // two // three
可以使用”()“进行插入值。
-
使用index(before:)and index(after:)方法访问给定索引之前和之后的索引String。要访问远离给定索引的索引,您可以使用该index(_:offsetBy:)方法,而不是多次调用其中一个方法。
let greeting = "Guten Tag!" greeting[greeting.startIndex] // G greeting[greeting.index(before: greeting.endIndex)] // ! greeting[greeting.index(after: greeting.startIndex)] // u let index = greeting.index(greeting.startIndex, offsetBy: 7) greeting[index] // a 注意:endIndex是最后一个字符的下一个字符的索引,greeting[greeting.endIndex] // Error
-
使用该indices属性访问字符串中单个字符的所有索引。
for index in greeting.indices { print("\(greeting[index]) ", terminator: "") } // Prints "G u t e n T a g ! " 注意: terminator:关键字表示不换行。
-
插入和删除(都是索引值,切记不是整数):
- 要将单个字符插入到指定索引的字符串中,请使用该insert(_:at:)方法,并在指定的索引处插入另一个字符串的内容,然后使用该insert(contentsOf:at:)方法。
- 要从指定索引的字符串中删除单个字符,请使用该remove(at:)方法,并删除指定范围内的子字符串,请使用以下removeSubrange(_:)方法:
比较字符串: ”==“,(Swift中的字符串和字符比较不区分大小写。)
前缀和后缀:要检查字符串是否具有特定的字符串前缀或后缀,请调用字符串hasPrefix("字符串")和 hasSuffix("字符串")方法
-
UTF-8、UTF-16和Unicode表示字符串
for codeUnit in dogString.utf8 { print("\(codeUnit) ", terminator: "") } print("") // Prints "68 111 103 226 128 188 240 159 144 182 " for codeUnit in dogString.utf16 { print("\(codeUnit) ", terminator: "") } print("") // Prints "68 111 103 8252 55357 56374 " for scalar in dogString.unicodeScalars { print("\(scalar.value) ", terminator: "") } print("") // Prints "68 111 103 8252 128054 " for scalar in dogString.unicodeScalars { print("\(scalar) ", terminator: "") } //Prints "D o g !! "
集合类型
-
数组遍历:
定义:var someInts = [Int]() var threeDoubles = Array(repeating: 0.0, count: 3) // threeDoubles is of type [Double], and equals [0.0, 0.0, 0.0] var shoppingList: [String] = ["Eggs", "Milk"] for (index, value) in shoppingList.enumerated() { print("Item \(index + 1): \(value)") } // Item 1: Six eggs // Item 2: Milk // Item 3: Flour // Item 4: Baking Powder // Item 5: Bananas
集合:
-
定义:
var letters = Set
() or var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"] - 使用该intersection(_:)方法创建一个仅具有两个集合通用值的新集合。
- 使用该symmetricDifference(_:)方法创建一个新集合,其中的值可以是任一集,但不能同时使用。
- 使用该union(_:)方法创建一个新集合,其中所有值都在两个集合中。
- 使用该subtracting(_:)方法创建一个新集合,其值不在指定的集合中。
- 使用“等于”运算符(==)来确定两个集合是否包含所有相同的值。
- 使用该isSubset(of:)方法确定集合的所有值是否包含在指定的集合中。
- 使用该isSuperset(of:)方法来确定集合是否包含指定集合中的所有值。
- 使用isStrictSubset(of:)或isStrictSuperset(of:)方法来确定集合是子集还是超集,但不等于指定集。
- 使用该isDisjoint(with:)方法来确定两个集合是否没有共同的值。
字典:
-
定义:
var namesOfIntegers = [Int: String]() // namesOfIntegers is an empty [Int: String] dictionary var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
-
遍历
for (airportCode, airportName) in airports { print("\(airportCode): \(airportName)") } // YYZ: Toronto Pearson // LHR: London Heathrow 等价于下面: for airportCode in airports.keys { print("Airport code: \(airportCode)") } // Airport code: YYZ // Airport code: LHR for airportName in airports.values { print("Airport name: \(airportName)") } // Airport name: Toronto Pearson // Airport name: London Heathrow
-
新的遍历方式:
使用该stride(from:to:by:)功能跳过不需要的标记。 let minuteInterval = 5 for tickMark in stride(from: 0, to: minutes, by: minuteInterval) { // render the tick mark every 5 minutes (0, 5, 10, 15 ... 45, 50, 55) } 也可以使用闭合范围stride(from:through:by:): let hours = 12 let hourInterval = 3 for tickMark in stride(from: 3, through: hours, by: hourInterval) { // render the tick mark every 3 hours (3, 6, 9, 12) }