Swift 5.1 (2) - 運算符

級別: ★☆☆☆☆
標簽:「iOS」「Swift 5.1」「運算符」
作者: 沐靈洛
審校: QiShare團隊


運算符的術語:操作符分為一元,二元,三元。

  • 一元運算符主要操作一個單一的目標(比如:-a)。一元前綴運算符可以直接出現在它們的目標前面(比如:!b),一元后綴運算符直接出現在它們目標之后(比如:c!)。
  • 二元運算符在兩個目標(例如2 + 3)上運行,并且是中綴,因為它們出現在兩個目標之間。
  • 三元運算符在三個目標上進行運算。與C一樣,Swift只有一個三元運算符,即三元條件運算符(a?b:c)

賦值運算符: 賦值運算符(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 {//!< '='運算符在swift中沒有返回值,所以此處這樣寫是無效的,同時會報錯。
        }

此功能可防止在實際使用等于運算符==時意外使用賦值運算符=,通過使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的溢出運算符(例如&+ b)來選擇值溢出行為。請參閱溢出運算符
字符串連接也支持加法運算符:

"hello, " + "world"  // equals "hello, world"

求余運算符:余數運算符(a%b)計算出a中將包含多少個b,并返回剩余的值(稱為余數)

9 % 4    // equals 1
-9 % 4   // equals -1

一元-+運算符:可以使用-(稱為一元減運算符)直接添加于運行的值之前,沒有任何空格,切換數值的符號。使用+(稱為一元加運算符)直接添加于運行的值之前,沒有任何空格,一元加運算符+只返回它操作的值,沒有任何變化。
一元減運算符

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

即使一元加運算符實際上沒有做任何事情,但是當使用一元減運算符作為負數時,我們可以使用它來為代碼提供正數的對稱性。
復合賦值運算符::與C一樣,Swift提供了將賦值=與另一個操作符相結合的復合賦值運算符。比如加法賦值運算符+ =

var a = 1
a += 2// a is now equal to 3

表達式a += 2a = a + 2的簡寫。實際上,加法和賦值操作符被組合成一個同時執行兩個任務的運算符。
需要注意的是:復合賦值運算符不返回值。例如:不能寫let b = a += 2
比較運算符: Swift支持所有標準C比較運算符。

  • 等于 == , 如:(a == b)
  • 不等于!=, 如: (a != b)
  • 大于>, 如: (a > b)
  • 小于<, 如: (a < b)
  • 大于等于>=, 如: (a >= b)
  • 小于等于!=, 如: (a <= b)
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" {
    print("hello, world")
} else {
    print("I'm sorry \(name), but I don't recognize you")
}
// Prints "hello, world", because name is indeed equal to "world".

比較元組:如果它們具有相同的類型和相同的數值,則可以比較兩個元組。元組從左到右進行比較,一次一個值,直到比較發現兩個不相等的值。比較這兩個值,并且該比較的結果確定元組比較的總體結果。如果所有元素都相等,則元組本身是相等的。即:在可以比較的前提下,只要按順序比較找到兩個元組中不相同的兩個值,則進行比較并且返回,作為元組的比較結果,后面的值將不再進行比較例如:

(1, "zebra") < (2, "apple")   //返回 true 因為1 小于2  "zebra" 和 "apple" 將不比較:“ zebra”不小于“apple”并不重要,因為比較已經由元組的第一個元素決定,當元組的第一個元素相同時,它們的第二個元素會被比較。
但是,當元組的第一個元素相同時,它們的第二個元素會被比較,下面就是這種情況
(3, "apple") < (3, "bird")    // 返回 true 因為 3 等于 3, "apple"小于"bird"
(4, "dog") == (4, "dog")      //返回 true 因為 4 等于 4, "dog" 等于"dog"

另:只有當給定運算符可以應用于相應元組中的每個值時,才能將元組運用給定運算符進行比較。
例如,如下面的代碼所示,您可以比較兩個類型(String,Int)的元組,因為可以使用<運算符比較StringInt值。相反,兩個類型(String,Bool)的元組不能與<運算符進行比較,因為<運算符不能應用于Bool值。

if ("blue", -1) < ("purple", 1)  {
    print("結果成立,返回了true")
}
if ("blue", false) < ("purple", true) {//!< 編譯器直接會報錯
    print("Binary operator '<' cannot be applied to two '(String, Bool)' operands")
}

Swift標準庫包含的比較元組時,只限于元組少于7個元素。要將元組與七個或更多元素進行比較,我們必須自己實現比較運算符。

另外:Swift還提供了兩個標識運算符(===和!==),用于測試兩個對象引用是否都引用同一個對象實例
身份運算符: 因為類是引用類型,所以多個常量和變量可能引用同一個類的單個實例。(對于結構體和枚舉,情況也是如此,因為它們在分配給常量或變量或傳遞給函數時總是被復制)Swift 提供了兩個身份運算符來找出兩個常量或變量是否完全引用類的相同實例。

  • 相同 (===)
  • 不相同 (!==)

注意:相同===并不意味著等于=====意味著類類型(class type)的兩個常量或變量引用了完全相同的類實例。等于意味著兩個實例在值上被認為是相等的。
1.obj1和obj2常量都是類類型,兩者引用了不相同的類的實例對象

let obj1 = UIView.init()
let obj2 = UIView.init()
let (x,y) = (obj1,obj2)
if x === y {
   print("obj1和obj2常量都是類類型,并且兩者引用了完全相同的類的實例對象")
} else{
   print("obj1和obj2常量都是類類型,兩者引用了不相同的類的實例對象")//!< 打印結果
}
  1. obj1和obj2常量都是類類型,并且兩者引用了完全相同的類的實例對象
let obj1 = UIView.init()
let obj2 = obj1
let (x,y) = (obj1,obj2)
if x !== y {
    print("obj1和obj2常量都是類類型,兩者引用了不相同的類的實例對象")
} else{
    print("obj1和obj2常量都是類類型,并且兩者引用了完全相同的類的實例對象")//!< 打印結果
}

三元條件運算符:三元條件運算符是一個特殊的運算符,有三個部分,使用用形式:question ? answer1 : answer2。如果問題為真,則返回answer1;否則返回answer2。
三元條件運算符是以下代碼的簡寫:

if question {
    answer1
} else {
    answer2
}

可Nil合并(Nil-Coalescing)運算符:nil-coalescing運算符??解包一個可選的a使用形式:a ?? b。解讀為:解包可選a;如果anil,則返回默認值b,否則返回a。表達式中a始終是可選類型。并且b必須與a的類型匹配。
nil-coalescing運算符是下面代碼的簡寫:

a! =  nil  ?  a!  :  b //<! 使用三元條件運算符和強制解包(a!)來訪問包含在a不是nil時的值,否則返回b

上面的代碼使用三元條件運算符和強制解包a!來訪問包含在可選的a中的值,若不是nil時,則不去管b的值,并返回a中的值,否則返回b

let defaultColorName = "red"
var userDefinedColorName: String?   // defaults to nil
var colorNameToUse = userDefinedColorName ?? defaultColorName

返回運算符: Swift包含多個范圍運算符。
1.封閉范圍運算符(Close Range Operator):封閉范圍運算符...,使用形式(a ... b)定義從ab的范圍,并包括值ab并且a的值不得大于b
當我們希望在所有值的全部范圍內進行遍歷時,閉合范圍運算符非常有用,例如使用for-in循環:

for item in 1...8 {
    print(item)//!< 打印 12345678
}

2.半開范圍運算符(Half-Open Range Operator):半開范圍運算符..<使用形式:a .. <b定義從ab的范圍,但不包括b,它被認為是半開放的,因為只包含它的第一個值卻沒有它的最終值。與封閉范圍運算符一樣,a的值不得大于b。如果a的值等于b,則最終有效范圍將為空。
當我們遍歷基于零的列表(如數組),因為數組的長度需要計算,此時根據定義,使用半開范圍運算符是最合適的。

/*打印結果:
 索引:0,對應字符串:i
 索引:1,對應字符串:am
 索引:2,對應字符串:zhangfei
*/
let array = ["i","am","zhangfei"]
for index in 0 ..< array.count { //!< 遍歷數組
    print("索引:\(index),對應字符串:\(array[index])")
}
//直接輸出字符串,形式
let array = ["i","am","zhangfei"]
for str in array[0..<array.count] {
    print(str)
}

3.局部(單面/側)范圍(One-Sided Ranges):封閉范圍運算符(Close Range Operator)半開范圍運算符(Half-Open Range Operator)的使用延伸。
封閉范圍運算符有一個替代形式,用于使范圍在一個方向上盡可能繼續。例如:一個數組從索引位置2到數組末尾的所有元素的范圍。這種情況下我們可以省略運算符一側的值。具體使用:

let array = ["i","am","zhangfei"]
//直接輸出字符串 形式1
for str in array[...]{
    print(str)
}
//直接輸出字符串 形式2 此處`1`可以是數組范圍內小于`array.count-1`的任意值
for str in array[1...] {
    print(str)
}
//直接輸出字符串 形式3 此處`(array.count-1)`可以是數組范圍內大于0的任意值
for str in array[...(array.count-1)] {
    print(str)
}

半開放范圍操作符也具有單側形式,僅使用其最終值編寫,最終值不是范圍的一部分,因為是小于<。具體使用

//直接輸出字符串 形式4 
for str in array[..<array.count] {
    print(str)
}

局部(單面/側)范圍(One-Sided Ranges)可以在其他上下文中使用,而不僅僅在下標中使用。在需要遍歷的情況下不能忽略了單側范圍的第一個值,因為遍歷需要清楚的知道應該從哪里開始。我們卻可以使用忽略了最終值單側范圍,但是范圍可以無限期的繼續,所以需要確保為我們的循環添加顯式結束條件,我們還可以檢查單側范圍是否包含特定的值。具體示例如下:

let range = ...5
range.contains(7)   // false
range.contains(4)   // true
range.contains(-1)  // true

關于范圍可以無限期的繼續,所以需要確保為我們的循環添加顯式結束條件舉例如下:

let range =  0...
for i in range {//!< 代碼無限期的執行
    print(i)
}

邏輯運算符: 邏輯運算符修改Boolean邏輯值為truefalse
Swift支持基于C語言的三個標準邏輯運算符。

  • 邏輯非 ! 如:!a
  • 邏輯與 &&如:a && b
  • 邏輯或 ||如:a || b

參考資料:
swift 5.1官方編程指南


推薦文章:
Swift 5.1(1) - 基礎
iOS UI狀態保存和恢復(三)
iOS UI狀態保存和恢復(二)
iOS UI狀態保存和恢復(一)
iOS 中精確定時的常用方法
Sign In With Apple(一)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,772評論 3 422
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,947評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,960評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,350評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,549評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,104評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,914評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,089評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,340評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,834評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,106評論 2 375

推薦閱讀更多精彩內容