Swift002-運(yùn)算符和流程控制語句
運(yùn)算符
Swift支持大多數(shù)標(biāo)準(zhǔn)C運(yùn)算符,并有所改進(jìn)。
- 賦值運(yùn)算符(=)不返回值,以防止在相等運(yùn)算(==)意圖時錯誤地使用它。
- 算術(shù)運(yùn)算符(+,-,*,/,%等)檢測和禁止值溢出,避免數(shù)據(jù)比類型允許范圍更大或更小
- 在面對數(shù)值溢出行為可以選擇使用溢出運(yùn)算符,在溢出運(yùn)算符中描述。
- 提供了在C中不存在的區(qū)間運(yùn)算符,如a..<b和a...b表示一系列值范圍的快捷方式。
按目標(biāo)數(shù)量分類
按操作數(shù)分為:一元運(yùn)算符、二元運(yùn)算符、三元運(yùn)算符(也有習(xí)慣成目,如三目運(yùn)算符)
- 一元運(yùn)算符 作用于單個目標(biāo)(在前面則前綴一元運(yùn)算符,后面則后綴一元運(yùn)算符),如:-a !a a!
- 二元運(yùn)算符 作用于兩個目標(biāo),是中綴運(yùn)算符, 如:a+b
- 三元運(yùn)算符 作用于三個目標(biāo)(Swift同OC一樣只有一個三元運(yùn)算符 a?b:c)
按功能作用分類
- 賦值運(yùn)算符 =
- 算術(shù)運(yùn)算符 + - * / % (Swift默認(rèn)禁止值溢出,但可使用溢出符號選擇溢出行為: a &+ b,另外+可用于String連接)
- 一元加減運(yùn)算符 + - (let a = -10086)
- 復(fù)合賦值運(yùn)算符 += -=
- 比較運(yùn)算符 == != > < >= <= (Swift還提供了恒等運(yùn)算符 === !==)
- 三元條件運(yùn)算符 ?: (可以將if else 進(jìn)行簡化)
- Nil-Coalescing運(yùn)算符 (a??b 表示 (a!=nil)?(a!):b, a!表示必然有值強(qiáng)制解包,a不為nil則不管b,這也稱為短路評估)
- 區(qū)間運(yùn)算符 (a...b 區(qū)間表示[a,b],a..<b區(qū)間表示[a,b),單向區(qū)間a...和..<b,分別表示a到結(jié)尾和起始到b但不包含b)
- 邏輯運(yùn)算符 ! && || (分別非 且 或)
注:
reversed()結(jié)合區(qū)間運(yùn)算符則倒序
for i in (0..<10).reversed() {
print(i)
}
// 9 8 7 6 5 4 3 2 1 0
字符串范圍結(jié)合區(qū)間運(yùn)算符
let msg = "www.google.com"
// 不使用區(qū)間運(yùn)算符
let index1 = msg.index(msg.startIndex, offsetBy: 4)
let index2 = msg.index(msg.startIndex, offsetBy: 6)
let range1 = Range(uncheckedBounds: (lower: index1, upper: index2))
let subStr1 = msg.substring(with: range)
print(subStr1)
// 使用區(qū)間運(yùn)算符
let range2 = msg.index(msg.startIndex, offsetBy: 4)..<msg.index(msg.startIndex, offsetBy: 6)
let subStr2 = msg.substring(with: range2)
print(subStr2)
區(qū)間運(yùn)算符除了返回一個Range外,還可以接受Comparable的輸入,返回ClosedInterval或HalfOpenInterval
// 我們可以用這個特性檢查字符串里的字符是不是都是合法字符(如是不是都是小寫)
let words = "Welcome!"
let interval = "a"..."z"
for c in words.characters {
if !interval.contains(String(c)){
print("\(c)不是小寫字母")
}
}
// W不是小寫字母 !不是小寫字母
流程控制語句
if... (if...else...)
public class func testIf() {
let a = 1
let b = 2
// 可以不帶括號
if a < b {
print("a>b")
}
}
let settingURL = URL(string: UIApplication.openSettingsURLString)!
if UIApplication.shared.canOpenURL(settingURL) {
if #available(iOS 10, *) {
UIApplication.shared.open(settingURL, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(settingURL)
}
}
switch
public class func testSwitch() {
// Swift中不需在用break跳出switch。若想用C風(fēng)格的落入特性,需給case分支插入fallthrough語句
let fruit = "apple"
switch fruit {
case "apple": print("good"); fallthrough // 用分號結(jié)束寫到同一行
case "banana","orange": print("great")
default: print("bad")
}
// case分支還可以進(jìn)行區(qū)間匹配
let age = 5
switch age {
case 0...11: print("少兒")
case 12...18: print("少年")
default: print("其他")
}
// case分支同樣支持單側(cè)區(qū)間匹配
let num = -5
switch num {
case ..<0: print("負(fù)數(shù)")
case 0...: print("正數(shù)")
default: print("0")
}
// 使用元組匹配(如:判斷屬于哪個象限)
let point = (2,2)
switch point {
case (0,0): print("坐標(biāo)在原點(diǎn)")
case (_,0): print("坐標(biāo)在x軸上")
case (0,_): print("坐標(biāo)在y軸上")
default: print("在象限區(qū)域")
}
// case中還可以使用where關(guān)鍵字來做額外的判斷條件
let height = 1.72
switch height{
case 1...3 where height == 1.72: print("case 1")
case 1...3 where height == 2: print("case 2")
default: print("default")
}
// 值綁定
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
// 復(fù)合案例
let someCharacter: Character = "e"
switch someCharacter {
case "a", "e", "i", "o", "u":
print("\(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m",
"n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
print("\(someCharacter) is a consonant")
default:
print("\(someCharacter) is not a vowel or a consonant")
}
// e is a vowel
// 復(fù)合案例 結(jié)合 值綁定
let stillAnotherPoint = (9, 0)
switch stillAnotherPoint {
case (let distance, 0), (0, let distance):
print("On an axis, \(distance) from the origin")
default:
print("Not on an axis")
}
// On an axis, 9 from the origin
}
for
public class func testFor() {
// C-style for statement has been removed in Swift 3
//for var i=1; i<100; i++ {
// print("\(i)")
//}
// for-in
for chare in "Google" {
print(chare)
}
// forEach
(1...10).forEach {
print($0)
}
}
控制轉(zhuǎn)移語句
- continue
continue語句告訴循環(huán)停止當(dāng)前循環(huán)不再往下執(zhí)行,進(jìn)入下次循環(huán)。即“完成了當(dāng)前的循環(huán)迭代”而沒有離開循環(huán)。
public class func testContinue() {
let startStr = "www.google.com www.apple.com"
var endStr = ""
let charactersToRemove: [Character] = ["a", "e", "i", "o", "u", " "]
for character in startStr {
if charactersToRemove.contains(character) {
continue
}
endStr.append(character)
}
print(endStr) // www.ggl.cmwww.ppl.cm
}
- break
break語句立即結(jié)束整個控制流語句的執(zhí)行,盡管break在Swift中不需要,但仍可用來中斷匹配。
public class func testBreak() {
let numberSymbol: Character = "三"
var possibleIntegerValue: Int?
switch numberSymbol {
case "1", "?", "一", "?":
possibleIntegerValue = 1
case "2", "?", "二", "?":
possibleIntegerValue = 2
case "3", "?", "三", "?":
possibleIntegerValue = 3
case "4", "?", "四", "?":
possibleIntegerValue = 4
default:
break
}
if let integerValue = possibleIntegerValue {
print("The integer value of \(numberSymbol) is \(integerValue).")
} else {
print("An integer value could not be found for \(numberSymbol).")
}
// The integer value of 三 is 3.
}
- fallthrough
在Swift中,switch語句不會落入每個案例的底部并進(jìn)入下一個案例。也就是說,switch一旦第一個匹配的案例完成,整個語句就完成了它的執(zhí)行。相反,C要求break在每個switch案例的末尾插入一個明確的語句,以防止通過。避免默認(rèn)的下降意味著Swift switch語句比C中的對應(yīng)語句更簡潔和可預(yù)測,因此它們避免switch錯誤地執(zhí)行多個案例。
如果需要C樣式的直通行為,則可以使用fallthrough關(guān)鍵字逐個選擇加入此行為。以下示例fallthrough用于創(chuàng)建數(shù)字的文本描述。
- return
用于提前退出,不再執(zhí)行代碼段中代碼
public class func testReturn(_ fruit:[String: String]) {
guard let price = fruit["price"] else {
return
}
print("price is \(price)")
}
- throw
守護(hù)關(guān)鍵字 guard
其實(shí)是if...else...變種,滿足guard語句的條件則跳過else向下執(zhí)行,否則執(zhí)行else中語句
else分支必須轉(zhuǎn)移控制以退出guard語句出現(xiàn)的代碼塊,如return,break,continue,或throw,也可以調(diào)用一個函數(shù)或方法不返回,如fatalError()。
public class func testReturn(_ fruit:[String: String]) {
guard let price = fruit["price"] else {
return
}
guard let name = fruit["name"] else {
fatalError("致命錯誤:不存在name鍵值")
}
print("price is \(price)")
}
自定義致命錯誤fatalError
public class func testFatalError(){
// (1) fatal error發(fā)生時,defer是不會執(zhí)行的
// (2) catch 不到 fatal error
defer {
print("defer here") // 不執(zhí)行
}
do {
try _throwsMyFatalError() // 產(chǎn)生fatal error
} catch let err {
print("in MyFatalError catch section \(err)") // 這一行進(jìn)不了
}
}
private class func _throwsMyFatalError() throws {
fatalError("my fatal error here!")
}
標(biāo)簽語句
在Swift中,可以在其他循環(huán)和條件語句中嵌套循環(huán)和條件語句,以創(chuàng)建復(fù)雜的控制流結(jié)構(gòu)。但是,循環(huán)和條件語句都可以使用break語句過早地結(jié)束執(zhí)行。因此,有時候明確要求break語句終止的循環(huán)或條件語句是有用的。類似地,如果有多個嵌套循環(huán),那么明確該continue語句應(yīng)該影響哪個循環(huán)可能很有用。
要實(shí)現(xiàn)這些目標(biāo),可以使用語句標(biāo)簽標(biāo)記循環(huán)語句或條件語句。使用條件語句,可以使用帶標(biāo)簽語句的break語句來結(jié)束帶標(biāo)簽語句的執(zhí)行。使用循環(huán)語句,可以使用帶有標(biāo)簽語句的break、continue語句來結(jié)束或繼續(xù)執(zhí)行帶標(biāo)簽的語句。
標(biāo)簽語句通過在語句相同行上關(guān)鍵字前放置標(biāo)簽名來指示,后跟冒號。這是while循環(huán)的這種語法的一個例子,然而所有循環(huán)和switch語句的原理是相同的:
public class func testLabel() {
let finishIndex = 25
var currentIndex = 0
var diceRoll = 0
gameLoop: while currentIndex != finishIndex {
diceRoll += 1
if diceRoll == 7 { diceRoll = 1 }
switch currentIndex + diceRoll {
case finishIndex:
break gameLoop
case let newSquare where newSquare > finishIndex:
continue gameLoop
default:
currentIndex += diceRoll
}
}
}
運(yùn)算符重載
讓已有的運(yùn)算符對自定義的類(結(jié)構(gòu))進(jìn)行運(yùn)算或重新定義已有運(yùn)算符的運(yùn)算規(guī)則,這種機(jī)制被稱為運(yùn)算符重載。
- 通過重載加號運(yùn)算符,使自定義的兩個坐標(biāo)結(jié)構(gòu)體對象實(shí)現(xiàn)相加
struct CenterPointer{
var x=0, y=0
}
func + (left:CenterPointer, right:CenterPointer) -> CenterPointer{
return CenterPointer(x:left.x+right.x, y:left.y+right.y)
}
let pointer1 = CenterPointer(x:2, y:3)
let pointer2 = CenterPointer(x:4, y:5)
let pointer3 = pointer1 + pointer2
- 重載判斷運(yùn)算符,實(shí)現(xiàn)判斷自定義類型是否相等
func == (left:CenterPointer, right:CenterPointer) -> Bool {
return (left.x == right.x) && (left.y == right.y)
}
func != (left:CenterPointer, right:CenterPointer) -> Bool {
return !(left == right)
}
- 組合運(yùn)算符,即將其他運(yùn)算符和賦值運(yùn)算符組合在一起,注意把運(yùn)算符左參數(shù)設(shè)置成inout類型
func += (left:inout CenterPointer, right:CenterPointer){
left = left + right
}
var pointer1 = CenterPointer(x:2, y:3)
var pointer2 = CenterPointer(x:4, y:5)
pointer1 += pointer2