使用 ?? 运算符为可为空变量设置默认值,表达式 A ?? B 中,如果 A 的值为 nil,则表达式的值为默认值 B
1 2 3
let nickname: String? =nil let fullName: String="John Appleseed" let informalGreeting ="Hi \(nickname ?? fullName)"
在 if 语句中处理可为空量时,也可以省略创建一个局部变量(常量?)的过程,在分支中直接访问原变量。
1 2 3
iflet nickname { print("Hey, \(nickname)") }
switch
switch 支持任意数据类型,和多种比较运算
1 2 3 4 5 6 7 8 9 10 11 12
let vegetable ="red pepper" switch vegetable { case"celery": print("Add some raisins and make ants on a log.") case"cucumber", "watercress": print("That would make a good tea sandwich.") caselet x where x.hasSuffix("pepper"): print("Is it a spicy \(x)?") default: print("Everything tastes good in soup.") } // Prints "Is it a spicy red pepper?"
let 可以在模式中使用,将匹配模式的值赋值给给定常量。
switch 执行完匹配的 case 会自动退出,swift 不需要 break 关键字手动退出
for-in
可以用 for-in 迭代字典中的键值对,字典是无序容器,因此迭代的顺序是任意的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
let interestingNumbers = [ "Prime": [2, 3, 5, 7, 11, 13], "Fibonacci": [1, 1, 2, 3, 5, 8], "Square": [1, 4, 9, 16, 25], ] var largest =0 for (_, numbers) in interestingNumbers { for number in numbers { if number > largest { largest = number } } } print(largest) // Prints "25"
while
while循环在指定条件满足时循环,而 repeat…while 循环至少循环一次。
1 2 3 4 5 6 7 8 9 10 11 12 13
var n =2 while n <100 { n *=2 } print(n) // Prints "128"
var m =2 repeat { m *=2 } while m <100 print(m) // Prints "128"
使用 ..<,每次循环可以得到一个下标,..<产生的下标不包含上限,而...包含上限。
1 2 3 4 5 6
var total =0 for i in0..<4 { total += i } print(total) // Prints "6"
overridefuncsimpleDescription() -> String { return"A square with sides of length \(sideLength)." } } let test =Square(sideLength: 5.2, name: "my test square") test.area() test.simpleDescription()
enumRank: Int { case ace =1 case two, three, four, five, six, seven, eight, nine, ten case jack, queen, king
funcsimpleDescription() -> String { switchself { case .ace: return"ace" case .jack: return"jack" case .queen: return"queen" case .king: return"king" default: returnString(self.rawValue) } } } let ace =Rank.ace let aceRawValue = ace.rawValue
funcsimpleDescription() -> String { switchself { case .spades: return"spades" case .hearts: return"hearts" case .diamonds: return"diamonds" case .clubs: return"clubs" } } } let hearts =Suit.hearts let heartsDescription = hearts.simpleDescription()
enumServerResponse { case result(String, String) case failure(String) }
let success =ServerResponse.result("6:00 am", "8:09 pm") let failure =ServerResponse.failure("Out of cheese.")
switch success { caselet .result(sunrise, sunset): print("Sunrise is at \(sunrise) and sunset is at \(sunset).") caselet .failure(message): print("Failure... \(message)") } // Prints "Sunrise is at 6:00 am and sunset is at 8:09 pm."
classSimpleClass: ExampleProtocol { var simpleDescription: String="A very simple class." var anotherProperty: Int=69105 funcadjust() { simpleDescription +=" Now 100% adjusted." } } var a =SimpleClass() a.adjust() let aDescription = a.simpleDescription
structSimpleStructure: ExampleProtocol { var simpleDescription: String="A simple structure" mutatingfuncadjust() { simpleDescription +=" (adjusted)" } } var b =SimpleStructure() b.adjust() let bDescription = b.simpleDescription
extensionInt: ExampleProtocol { var simpleDescription: String { return"The number \(self)" } mutatingfuncadjust() { self+=42 } } print(7.simpleDescription) // Prints "The number 7"
错误处理
Error
可以用任何适配 Error 协议的类型表示错误。
1 2 3 4 5
enumPrinterError: Error { case outOfPaper case noToner case onFire }
使用 throw 关键字抛出错误,使用 throws 关键字标记一个函数会抛出错误。
如果在函数中抛出错误,函数的执行立即终止,调用该函数的地方需要处理抛出的错误。
1 2 3 4 5 6
funcsend(job: Int, toPrinterprinterName: String) throws -> String { if printerName =="Never Has Toner" { throwPrinterError.noToner } return"Job sent" }
do-catch
有多种方法处理错误,其一是 do-catch,在 do 块中,用 try 标记可能会抛出错误的调用,在 catch 块中,抛出的错误被自动命名为 error,你也可以指定其他名字。
1 2 3 4 5 6 7
do { let printerResponse =try send(job: 1040, toPrinter: "Bi Sheng") print(printerResponse) } catch { print(error) } // Prints "Job sent"
catch块可有多个,在 catch 后声明要匹配的模式,用以捕获具体的错误。
1 2 3 4 5 6 7 8 9 10 11
do { let printerResponse =try send(job: 1440, toPrinter: "Gutenberg") print(printerResponse) } catchPrinterError.onFire { print("I'll just put this over here, with the rest of the fire.") } catchlet printerError asPrinterError { print("Printer error: \(printerError).") } catch { print(error) } // Prints "Job sent"
// Reimplement the Swift standard library's optional type enumOptionalValue<Wrapped> { case none casesome(Wrapped) } var possibleInteger: OptionalValue<Int> = .none possibleInteger = .some(100)
类型参数限制
在代码块前书写 where 子句声明对泛型参数的要求,例如,要求泛型参数必须符合某协议,要求两个类型相同,要求某参数必须是一个父类的子类
1 2 3 4 5 6 7 8 9 10 11 12 13
funcanyCommonElements<T: Sequence, U: Sequence>(_lhs: T, _rhs: U) -> Bool whereT.Element: Equatable, T.Element==U.Element { for lhsItem in lhs { for rhsItem in rhs { if lhsItem == rhsItem { returntrue } } } returnfalse } anyCommonElements([1, 2, 3], [3])
在书写时,<T: Equatable> 等同于 <T> ... where T: Equatable。