運算子是一種特定的符號或運算式,用來檢驗、修改或合并變數。例如,用求和運算子+可以對兩個數字進行求和(如let i = 1 + 2);稍微複雜一點的例子有邏輯與操作符&& (如if enteredDoorCode && passedRetinaScan) ,自增長運算子 ++i (這是i=i+1的簡寫方式)
Swift支援C標準庫中的大多數運算子並提升了各自的相容性,從而可以排除常見的編碼錯誤。賦值操作符 (=)不會返回一個值,這樣可以防止你因粗心將賦值運算子 (=)寫成 (==)而引起錯誤。算術符(+、 -、 *、 /、 % 等)會檢查與駁回值溢出,這樣可以避免實值型別的資料在超過實值型別所允許的儲存範圍時,出現意想不到的資料。你可以選擇使用Swift所提供的值溢出運算子進行量化溢出的行為,詳細見溢出操作符。
與C語言不同,Swift允許你對浮點數執行取餘運算。同時,Swift提供兩個範圍的運算子 (a..b 和 a…b),作為表示一個數值範圍的簡寫方式,這點C不支援。
本章節描述了Swift常見運算子。進階運算子覆蓋了Swift的進階操作符,並且對自訂動作符,對自訂類型操作符的實現進行了描述。
術語
操作符都是一元、二元或三元:
◎一元操作符操作單個對象 (如 -a)。一元首碼操作符出現在對象前(如 !b),一元尾碼操作符在對象後出現 (如 i++)。
◎二元操作符操作兩個對象(如 2 + 3),並且操作符位於兩個元素中間。
◎三元操作符對兩個對象進行操作。與C一樣,Swift僅支援一個三元操作符:三元條件操作符 (a ? b : c).
操作符所影響的值被稱為運算元。運算式1 + 2中,符號 + 是一個二元運算子並且兩個運算元分別為 1 和 2。
賦值運算子
賦值運算子(a = b) 用b的值去初始化或更新a 的值
複製代碼 代碼如下:
let b = 10
var a = 5
a = b
// 此刻a的值為10
假如右邊賦值的資料為多個資料的元組,它的元素可以是一次性賦給的多個常量或變數
複製代碼 代碼如下:
let (x, y) = (1, 2)
// x等於1, 並且y等於2
與C及Objective-C不同,Swift中賦值運算子並不將自身作為一個值進行返回。所以以下的代碼是不合法的:
複製代碼 代碼如下:
if x = y {
// 錯誤, 因為x = y並不會返回一個值
}
此特性協助你避免因粗心將賦值運算子 (==)寫成 (=)而引起的錯誤。因為 if x = y 這樣寫是無效的。
數學運算子
Swift支援所有數字類型的四個標註運算子:
◎加法(+) *減法(-)
◎乘法(*)
◎除法(/)
例如:
複製代碼 代碼如下:
1 + 2 // equals 3
5 - 3 // equals 2
2 * 3 // equals 6
10.0 / 2.5 // equals 4.0
不同於C和Objective-C,預設情況下Swift的算術運算子不允許值溢出。你可以通過Swift的溢出運算子來選擇值的溢出情況(例如 a & + b)。詳見 Overflow Operators
加法運算子對字串串連也一樣適用,例如:
複製代碼 代碼如下:
"hello, " + "world" // equals "hello, world"
兩個字元,或者一個字元一個字串,能組合成一個新的字串:
複製代碼 代碼如下:
let dog: Character = "dog"(由於瀏覽器不能顯示狗的unicode映像,故用三個字母代替……)
let cow: Character = "cow"(同上……)
let dogCow = dog + cow
// dogCow is equal to "dogcow"
詳見Concatenating Strings and Characters
取餘運算子
取餘運算子(a % b)計算出a是b的幾倍然後返回被留下的值(餘數)。
註:餘數運算子(%)亦稱是其他語言的一個模數運算子。然而,其在Swift裡意味著如果對負數操作,嚴格上講,得到的是餘數而不是模數。
這是餘數運算子如何工作。 要計算9% 4,你首先得求出9是4的幾倍 :
9能去除兩個4,並且餘數是1 (顯示在橙色)。
在Swift中,這個將被寫成:
複製代碼 代碼如下:
9 % 4 // equals
確定a % b的答案, 運算子%計算下列等式並且返回餘數作為其輸出:
複製代碼 代碼如下:
a = (b × some multiplier) + remainder
some multiplier 是a裡面能包含b的最多倍數。
將9和4插入到公式:
複製代碼 代碼如下:
9 = (4 × 2) + 1
同一個方法是應用的,當計算a時的一個負值的餘數:
複製代碼 代碼如下:
-9 % 4 // equals -1
將-9和4插入到公式:
複製代碼 代碼如下:
-9 = (4 × -2) + -1
產生餘數值為-1。
b為負值時的b的符號被忽略,這意味著%b和%-b的結果是一樣的。
浮點餘數計算
不同於C和Objective-C,Swift的餘數運算子也能運用於浮點數:
複製代碼 代碼如下:
8 % 2.5 // equals 0.5
在本例中, 8用2.5來分等於3, 餘數是0.5,因此餘數為0.5。
自增和自減運算子
像C一樣,Swift提供一個自增運算子(++)和自減運算子(–)作為增加或減少一個數值的一種捷徑,增減量為1。 您能對任何整數或浮點類型的變數使用這些運算子。
複製代碼 代碼如下:
var i = 0
++i // i now equals 1
每當你使用 ++i ,i 的值增加1,本質上++i可以看做是i=i+1,同樣–i可以看做是i=i-1。
++和–符號可以使用作為首碼算符或作為尾碼運算子。++i 和 i++ 是兩個有效方式給i的值增加1,同樣, –i和i–如是。
注意這些運算子修改i並且傳回值。如果你只想要增加或減值i,您可以忽略傳回值。然而,如果你使用傳回值,根據下列規則將是不同的根據的您是否使用了運算子的首碼或尾碼版本,它:
◎如果運算子在變數之前被寫,它在返回其值之前增加變數。
◎如果運算子在變數之後被寫,它在返回其值之後增加變數。
例如:
var a = 0
let b = ++a
// a and b are now both equal to 1
let c = a++
// a is now equal to 2, but c has been set to the pre-increment value of 1
在上面的例子中,let b = ++a 中a在返回其值之前增加,這就是為什麼a和b的新值是等於1。
然而,let c = a++ 中a在返回其值之後增加,這意味著c獲得a的原值1,然後a自增,a等於2。
除非你需要特定工作情況下才使用i++,否則在所有的情況下建議你使用++i和–i, 因為他們修改i並傳回值的行為符合我們的預期。
一元減運算子
一個數值前加了符號-,叫作一元減運算子:
複製代碼 代碼如下:
let three = 3
let minusThree = -three // minusThree equals -3
let plusThree = -minusThree // plusThree equals 3, or "minus minus three"
一元減運算子(-)直接地被加在前面,在它起作用的值之前,不用任何空白空間。
一元加運算子
一元加運算子(+)返回它起作用的值,不做任何變動:
複製代碼 代碼如下:
let minusSix = -6
let alsoMinusSix = +minusSix // alsoMinusSix equals -6
雖然一元加上運算子實際上不執行什麼,當你也使用一元減負數的運算子時,你能使用它提供對稱的正數。
複合賦值操作符
Swift提供類似C語言的複合賦值操作符,即把賦值和另一個運算合并起來。舉個例子,像加法賦值運算子(+ =):
複製代碼 代碼如下:
var a = 1
a += 2
// a is now equal to 3
運算式 a += 2 比 a = a + 2更精鍊。加法賦值運算子能夠有效地把加法和賦值組合到一個運算,同時執行這兩個任務。
要注意的是,複合賦值操作符不傳回值。例如,你不能寫讓成let b = + = 2,這種行為不同於上面提到的遞增和遞減運算子。
複合賦值運算子的完整列表可以在[Expressions]那一章節找到
比較子
Swift支援所有標準c的比較子
等於 (a == b)
不等於(a != b)
大於 (a > b)
小於 (a < b)
大於等於 (a >= b)
小於等於(a <= b)
註:Swift 提供兩個恒等運算子(=== and !==),用它來測試兩個對象引用是否來自於同一個對象執行個體。詳見Classes and Structures。 每個比較操作符返回一個Bool值來表示語句是否為真:
複製代碼 代碼如下:
1 == 1 // true, because 1 is equal to 1
2 != 1 // true, because 2 is not equal to 1
2 > 1 // true, because 2 is greater than 1
1 < 2 // true, because 1 is less than 2
1 >= 1 // true, because 1 is greater than or equal to 1
2 <= 1 // false, because 2 is not less than or equal to 1
比較操作符通常用在條件陳述式,如if語句:
複製代碼 代碼如下:
let name = "world"
if name == "world" {
println("hello, world")
} else {
println("I'm sorry \(name), but I don't recognize you")
}
// prints "hello, world", because name is indeed equal to "world"
想要瞭解更多有關的if語句,請參閱控制流程。
三元條件運算子
三元條件運算子是一種特殊的運算子,有三個部分,其形式為question? answer1:answer2.這是一個用來測試兩種運算式基於輸入是真或是 假的捷徑。如果question? 為真時, 它評估answer1並返回其值; 否則,它評估answer2並返回其值。三元條件運算子是下面的代碼的簡化:
複製代碼 代碼如下:
if question {
answer1
} else {
answer2
}
這裡舉一個列子,計算一個表行像素的高度,如果行有一個頭,行高應該是50像素,比內容要高度要高。如果行沒有頭是20像素:
複製代碼 代碼如下:
let contentHeight = 40
let hasHeader = true
let rowHeight = contentHeight + (hasHeader ? 50 : 20)
// rowHeight is equal to 90
前面的例子也可以用下面的的代碼:
複製代碼 代碼如下:
let contentHeight = 40
let hasHeader = true
var rowHeight = contentHeight
if hasHeader {
rowHeight = rowHeight + 50
} else {
rowHeight = rowHeight + 20
}
// rowHeight is equal to 90
第一個例子使用的三元條件運算子,意味著rowHeight可以在一行代碼被設定為正確的值。這比第二個樣本更簡潔, 不需要課外的rowHeight變數, 因為它的價值不需要在一個if語句中修改。
三元條件運算子提供了一個高效的寫法來決定哪個運算式會被執行。不過還是請小心使用三元條件運算子,其簡潔性如果過度使用會導致閱讀代碼的困難。要避免多個執行個體的三元條件運算子組合成一個複合陳述式。
範圍運算子
Swift包含兩個範圍運算子,能快捷的表達一系列的值
封閉範圍運算子
封閉範圍運算子(a…b)定義了一個範圍,從a到b,並包括a和b的值。
當要在一個範圍內迭代所有可能的值的時候,範圍運算子是非常有用的, 例如for-in迴圈
複製代碼 代碼如下:
for index in 1...5 {
println("\(index) times 5 is \(index * 5)")
}
// 1 times 5 is 5
// 2 times 5 is 10
// 3 times 5 is 15
// 4 times 5 is 20
// 5 times 5 is 25
欲瞭解更多for-in迴圈,請參閱控制流程。
半封閉的地區運算子
半封閉的地區運算子(a..b)定義了從a到b的範圍,但不包括b。它被認為是半封閉的,因為它包含第一個值,而不包含最終值。
半封閉的範圍使用明確,當你使用從零開始的列表,如數組,它是有用的數到(但不包括)列表的長度:
複製代碼 代碼如下:
let names = ["Anna", "Alex", "Brian", "Jack"]
let count = names.count
for i in 0..count {
println("Person \(i + 1) is called \(names[i])")
}
// Person 1 is called Anna
// Person 2 is called Alex
// Person 3 is called Brian
// Person 4 is called Jack
請注意,該數組包含四個項目,但0 . .數只數到3(數組中的最後一個項目的索引),因為它是一個半封閉的範圍。欲瞭解更多有關數組的資訊,請參閱數組
邏輯運算子
邏輯運算子修改或結合布爾邏輯值true和false。Swift支援這三個標準邏輯運算子基於c語言:
◎Logical NOT (!a)
◎Logical AND (a && b)
◎Logical OR (a || b)
邏輯非運算子
邏輯非運算子(!a)轉化一個Bollean值,true變成false,false變成true。
邏輯操作符是一個首碼操作符, 並立即出現在它修飾的值之前,沒有任何空白,它被解讀為”不是”, 見下面的例子:
let allowedEntry = false
if !allowedEntry {
println("ACCESS DENIED")
}
// prints "ACCESS DENIED"
這句話if !allowedEntry 能理解為 “if not allowedEntry.” 只執行後續的行,如果“not allowedEntry” 是 true; 那就是說 if allowedEntry是false.
在這個例子中,精心挑選的布爾常量和變數名可以協助保持代碼的可讀性和簡潔,同時避免雙重否定或混亂的邏輯語句。
邏輯與運算子
邏輯與運算子:(A && B)建立的運算式中,A和B兩個值必須同時為true時運算式才正確。
其中A或者B有任一值是false時,邏輯與算符表示不成立,必須兩者同時為true時才成立。事實上,如果第一個值是false,第二個值甚至不會再進行判斷,因為必須是兩個值皆為true,已經有一方false、則沒必要再往下面進行判斷了。這被稱作短路條件。
以下這個例子判斷兩個Bool 類型的值,並只有這兩個值都為真的時候會輸出:Welcome。失敗則輸出”ACCESS DENIED”:
複製代碼 代碼如下:
let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan {
println("Welcome!")
} else {
println("ACCESS DENIED")
}
// prints "ACCESS DENIED”
邏輯或運算子
運算式(a || b)運算子中、只要a或者b有一個為true,運算式就成立。
與上面的邏輯與運算子相似,邏輯或運算子使用短路條件判斷,如果左邊是 true,那麼右邊不會被判斷,因為整體結果不會改變了。
在下面的例子中,第一個布爾值(hasDoorKey)為false,但第二個值(knowsOverridePassword)為true。因為兩者有一個值是true,整個運算式的計算結果也為true,正確輸出:Welcome!
複製代碼 代碼如下:
let hasDoorKey = false
let knowsOverridePassword = true
if hasDoorKey || knowsOverridePassword {
println("Welcome!")
} else {
println("ACCESS DENIED")
}
// prints "Welcome!"
複合邏輯運算式
你可以將多個邏輯運算子複合來建立更長的複合運算式:
複製代碼 代碼如下:
if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {
println("Welcome!")
} else {
println("ACCESS DENIED")
}
// prints "Welcome!"
相比於之前兩個單獨分開的運算子,本次通過多重嵌套、將我們上面的&&、|| 運算子相結合組合成一個較長的複合運算式。看起來有點饒人、其實本質還是兩兩相比較、可以簡單地看成A && B || C || D、從左往右根據運算子優先順序進行判斷、注意區分開&&、||、只要牢記運算邏輯&&需要兩者都為true、||則只需要一方為true則運算子正確即可解析整個複合運算式、透過現象看本質。
明確地括弧(翻譯成中文語句不連貫太特麼饒人了、怒了自己理解。)
複合運算式中,我們可以添加進()使確邏輯意圖更加明確,上面的例子中,我們可以在第一部分上加括弧來使意義更明確。
複製代碼 代碼如下:
if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword {
println("Welcome!")
} else {
println("ACCESS DENIED")
}
// prints "Welcome!"
在複合邏輯運算式中、我們可以使用括弧明確地表示我們需要將幾個值放在一個單獨的邏輯運算中去判斷得出結果、最後根據()內的結果再去與後面的值進行判斷、看上面的例子、就像我們小學學加減乘除一樣、如果沒有括弧()我們肯定是按照運算子的優先順序去判斷、但此時有了括弧、我們需要先運算其中的邏輯運算子得到它們的值.使用括弧()在符合邏輯運算式中可以更明確的你的意圖。