莎士比亚曾经说过:“To be or not to be, that is the question.“

这正好也是编程的逻辑中心问题:评估一个条件是真还是假。

今天我们一起来探讨学习Swift语言中的条件语句。

如何检查一个条件的真或假?

程序经常会做出选择:

  • 如果学生的考试成绩超过 80 分,则打印成功信息。
  • 如果用户输入的名字按字母顺序排列在朋友的名字之后,则将朋友的名字放在前面。
  • 如果在数组中添加数字后,数组中包含的条目超过 3 个,则删除最老的条目。
  • 如果用户被要求输入自己的名字,但却什么也没输入,那么就给他们一个 “匿名 “的默认名字。

Swift 使用 if 语句来处理这些问题,它允许我们检查一个条件,并在条件为真时运行一些代码。它们看起来像这样:

if someCondition {
    print("Do something")
}

让我们来分析一下:

  1. 条件以 if 开头,向 Swift 表示我们要在代码中检查某种条件。
  2. someCondition 部分是写入条件的地方——分数是否超过 80 分?数组是否包含 3 个以上的项目?这都是条件。
  3. 如果条件为真,即分数真的超过了 80 分,那么我们就打印 “Do something“信息。

当然,这并不是代码的全部: 我还没提到 { 和 } 符号。这些符号被称为大括号——更确切地说,是开大括号和闭大括号。

这些大括号在 Swift 中被广泛用于标记代码块:开头的大括号开始代码块,结尾的大括号结束代码块。在代码块中,如果我们的条件在检查时恰好为真,我们要运行的代码就会在代码块中出现,在我们的例子中就是打印一条消息。

你可以根据需要在代码块中加入尽可能多的代码:

if someCondition {
    print("Do something")
    print("Do something else")
    print("Do a third thing")
}

当然,真正重要的是 someCondition 部分,因为这才是你的检查代码:你到底想检查什么条件?

让我们以分数为例:如果分数常量超过 80,我们就打印一条信息。代码如下:

let score = 85

if score > 80 {
    print("Great job!")
}

在这段代码中,score > 80 是我们的条件。你应该还记得学校里 > 的意思是 “大于”,所以我们的完整条件是 “如果分数大于 80″。如果大于 80,就会打印出 “Great job!”。

这个 > 符号是一个比较运算符,因为它比较两个事物并返回布尔结果:左边的事物是否大于右边的事物?你还可以用 < 表示小于,用 >= 表示 “大于或等于”,用 <= 表示 “小于或等于”。

让我们试一试——你认为以下这段代码会打印出什么结果?

let speed = 88
let percentage = 85
let age = 18

if speed >= 88 {
    print("Where we're going we don't need roads.")
}

if percentage < 85 {
    print("Sorry, you failed the test.")
}

if age >= 18 {
    print("You're an adult.")
}

试着在头脑中运行代码——哪些 print() 行将会被实际运行?

那么,如果速度大于或等于 88,我们的第一行就会运行,因为它正好是 88,所以第一行 print() 代码就会运行。

第二行将在百分比小于 85 时运行,因为正好是 85,所以第二行 print() 不会运行——我们用的是小于,而不是小于或等于。

第三个将在年龄大于或等于 18 时运行,由于正好是 18,第三个 print() 将运行。

现在让我们试试第二个示例条件:如果用户输入的名字按字母顺序排列在其朋友名字的后面,则将朋友的名字放在前面。我们已经看到 <>= 和其他函数在处理数字时的出色表现,但它们在处理字符串时也同样出色:

let ourName = "Dave Lister"
let friendName = "Arnold Rimmer"

if ourName < friendName {
    print("It's \(ourName) vs \(friendName)")
}

if ourName > friendName {
    print("It's \(friendName) vs \(ourName)")
}

因此,如果按字母顺序排列时,ourName 中的字符串在 friendName 中的字符串之前,就会按照我们的要求先打印 ourName,然后再打印 friendName

让我们来看看第三个示例条件:如果向数组中添加一个数字使其包含的条目超过 3 个,则删除最老的条目。我们已经遇到过 append()count 和 remove(at:),所以现在我们可以把这三个条件组合在一起,像这样:

// Make an array of 3 numbers
var numbers = [1, 2, 3]

// Add a 4th
numbers.append(4)

// If we have over 3 items
if numbers.count > 3 {
    // Remove the oldest number
    numbers.remove(at: 0)
}

// Display the result
print(numbers)

现在让我们看看第四个示例条件:如果用户被要求输入姓名,但却什么也没输入,那么就给他们一个默认的 “匿名”姓名。

要解决这个问题,你首先需要认识另外两个你会经常用到的比较运算符,这两个运算符都是处理相等关系的。第一个是 ==,意思是 “等于”,使用方法如下:

let country = "Canada"

if country == "Australia" {
    print("YES")
}

第二个是 !=,意思是 “不等于”,用法如下:

let name = "Taylor Swift"

if name != "Anonymous" {
    print("Welcome, \(name)")
}

在我们的例子中,我们要检查用户输入的用户名是否为空,我们可以这样做:

// Create the username variable
var username = "taylorswift13"

// If `username` contains an empty string
if username == "" {
    // Make it equal to "Anonymous"
    username = "Anonymous"
}

// Now print a welcome message
print("Welcome, \(username)!")

该**""**是一个空字符串:我们从引号开始,到引号结束,中间没有任何内容。通过将用户名与之比较,我们可以检查用户是否也输入了空字符串作为用户名,这正是我们想要的。

现在,还有其他方法可以进行这种检查,重要的是要了解它们的作用。

首先,我们可以将字符串的计数(有多少个字母)与 0 进行比较,就像这样:

if username.count == 0 {
    username = "Anonymous"
}

在任何语言中,将一个字符串与另一个字符串进行比较都不会很快,因此我们用整数比较取代了字符串比较:字符串中的字母数是否等于 0?

在许多语言中这都非常快,但在 Swift 中却不是。要知道,Swift 支持各种复杂的字符串——几乎所有人类语言都可以使用,包括表情符号,而其他许多编程语言却无法做到这一点。不过,这种强大的支持也是有代价的,其中一个代价就是,如果要询问字符串的长度,Swift 就必须一个一个地数清所有字母,而不是将长度与字符串分开存储。

所以,想想看,如果你有一个庞大的字符串,其中存储了莎士比亚的全部作品。我们对 count == 0 的小检查必须遍历并计算字符串中的所有字母,尽管只要我们计算了至少一个字符,我们就知道了问题的答案。

因此,Swift 为其所有字符串、数组、字典和集合添加了第二个功能:isEmpty。如果你正在检查的东西里面什么都没有,它就会返回 true,我们可以用它来修复我们的条件,就像这样:

if username.isEmpty == true {
    username = "Anonymous"
}

这样更好,但我们还可以更进一步。要知道,最终最重要的是你的条件必须归结为 “true“或 “false“;Swift 不允许任何其他条件。在我们的例子中,username.isEmpty 已经是一个布尔值,这意味着它要么为真要么为假,所以我们可以让代码变得更简单:

if username.isEmpty {
    username = "Anonymous"
}

如果 isEmpty 为真,则条件通过,用户名被设置为匿名,否则条件失败。

Swift 如何让我们比较多种类型的数据?

Swift 可以让我们直接比较多种值,这意味着我们可以检查各种值是否相等并进行比较。例如,如果我们有如下值:

let firstName = "Paul"
let secondName = "Sophie"

let firstAge = 40
let secondAge = 10

然后,我们可以通过各种方式对它们进行比较:

print(firstName == secondName)
print(firstName != secondName)
print(firstName < secondName)
print(firstName >= secondName)

print(firstAge == secondAge)
print(firstAge != secondAge)
print(firstAge < secondAge)
print(firstAge >= secondAge)

在幕后,Swift 以一种非常巧妙的方式实现了这一点,它实际上可以比较各种各样的事物。例如,Swift 有一种用于存储日期的特殊类型,叫做 Date,你可以使用相同的运算符来比较日期:例如:someDate < someOtherDate

我们甚至可以要求 Swift 使我们的枚举具有可比性,就像下面这样:

enum Sizes: Comparable {
    case small
    case medium
    case large
}

let first = Sizes.small
let second = Sizes.large
print(first < second)

这将打印 “true“,因为在这个枚举列表中,small 排在 large 之前。

如何检查多个条件

当我们使用 if 时,我们必须提供 Swift 的某种条件,该条件在评估后要么为真,要么为假。如果要检查多个不同的值,可以像这样把它们一个接一个地放在一起:

let age = 16

if age >= 18 {
    print("You can vote in the next election.")
}

if age < 18 {
    print("Sorry, you're too young to vote.")
}

但仔细想想,这样做并不高效:我们的两个条件是相互排斥的,因为如果某人大于或等于 18(第一个条件),那么他就不可能小于 18(第二个条件),反之亦然。我们让 Swift 做了不需要做的工作。

在这种情况下,Swift 为我们提供了一种更高级的条件,让我们可以在代码中添加 else 块,即在条件不为真时运行一些代码。

使用 else,我们可以将之前的代码重写成这样:

let age = 16

if age >= 18 {
    print("You can vote in the next election.")
} else {
    print("Sorry, you're too young to vote.")
}

现在 Swift 只需检查一次年龄:如果大于或等于 18 岁,则运行第一段 print() 代码,但如果小于 18 岁,则运行第二段 print() 代码。

因此,现在我们的条件是这样的:

if someCondition {
    print("This will run if the condition is true")
} else {
    print("This will run if the condition is false")
}

还有一种更高级的条件叫 else if,它可以让你在第一项检查失败后运行新的检查。你可以根据需要只使用一个 else if,也可以使用多个 else if,甚至可以根据需要将 else if 与 else 结合使用。但是,else 只能有一个,因为这意味着 “如果所有其他条件都为假”。

下面就是这种情况:

let a = false
let b = true

if a {
    print("Code to run if a is true")
} else if b {
    print("Code to run if a is false but b is true")
} else {
    print("Code to run if both a and b are false")
}

如果需要,您可以不断添加更多的 else if 条件,但要注意代码不要太复杂!

除了使用 else 和 else if 来创建更高级的条件外,您还可以检查多件事情。例如,我们可能想说 “如果今天的温度超过 20 摄氏度但低于 30 摄氏度,则打印一条信息”。

这有两个条件,所以我们可以这样写:

let temp = 25

if temp > 20 {
    if temp < 30 {
        print("It's a nice day.")
    }
}

虽然这样做效果很好,但 Swift 提供了一个更简短的替代方法:我们可以使用 && 将两个条件组合在一起,只有当条件中的两个部分为真时,整个条件才会为真。

因此,我们可以把代码改成这样:

if temp > 20 && temp < 30 {
    print("It's a nice day.")
}

你应该把 && 读作 “并且”,这样我们的整个条件就变成了 “如果温度大于 20 并且小于 30,则打印一条信息”。之所以称其为逻辑运算符,是因为它能将布尔值组合成一个新的布尔值。

与**&&** 的对应的运算符是两个竖线 || ,意思是 “或”。&& 只有在两个子条件都为真的情况下才会使条件为真,而 || 则是在任何一个子条件都为真的情况下就会使条件为真。

例如,我们可以说,如果用户年满 18 周岁,就可以购买游戏;如果用户未满 18 周岁,则必须得到父母的许可。我们可以使用 || 这样写:

let userAge = 14
let hasParentalConsent = true

if userAge >= 18 || hasParentalConsent == true {
    print("You can buy the game")
}

这将打印出 “You can buy the game”,因为尽管我们条件的前半部分失败了,即用户未满 18 周岁,但后半部分通过了,因为他们确实获得了父母的同意。

请记住,可以去掉条件中的 == true,因为我们显然已经在检查布尔值了。因此,我们可以这样写:

if userAge >= 18 || hasParentalConsent {
    print("You can buy the game")
}

最后,让我们来尝试一个更复杂的示例,它同时结合了 ifelse ifelse 和 || 等条件,甚至还展示了枚举如何与条件相结合。

在这个示例中,我们将创建一个名为 TransportOption 的枚举,它包含五种情况:飞机、直升机、自行车、汽车和滑板车。然后,我们将把一个示例值赋值给一个常量,并进行一些检查:

  • 如果我们要乘飞机或直升机去某个地方,将打印 “Let’s fly!”
  • 如果我们要骑自行车,将打印 “I hope there’s a bike path…”
  • 如果我们开车,将打印 “Time to get stck in traffic.”。
  • 否则,会打印 “I’m going to hire a scooter now!”

代码如下:

enum TransportOption {
    case airplane, helicopter, bicycle, car, scooter
}

let transport = TransportOption.airplane

if transport == .airplane || transport == .helicopter {
    print("Let's fly!")
} else if transport == .bicycle {
    print("I hope there's a bike path…")
} else if transport == .car {
    print("Time to get stuck in traffic.")
} else {
    print("I'm going to hire a scooter now!")
}

我想说明一下代码中的几个部分:

  1. 当我们设置 transport 的值时,我们需要明确指出我们指的是 TransportOption.airplane。我们不能只写 .airplane,因为 Swift 不明白我们指的是 TransportOption 枚举。
  2. 一旦我们第一次写过了**TransportOption.airplane**,我们就不需要再写 TransportOption 了,因为 Swift 知道 transport 必须是某种 TransportOption。因此,我们可以检查它是否等于 .airplane 而不是 TransportOption.airplane
  3. 代码使用 || 来检查 transport 是否等于 .airplane 或等于 .helicopter,如果两者之一为真,则条件为真,并打印 “Let’s fly!”。
  4. 如果第一个条件失败,即运输模式不是**.airplane.helicopter,则运行第二个条件:运输模式是.bicycle**吗?如果是,则打印 “I hope there’s a bike path…”。
  5. 如果我们也不骑自行车,那么我们就检查我们是否开车。如果是,则打印 “Time to get stuck in traffic.”。
  6. 最后,如果前面的条件都不成立,则运行 else 代码块,这意味着我们要骑摩托车。

if 和 else if 有什么区别?

刚开始学习 Swift 时,可能很难知道什么时候该使用 else,什么时候该使用 else if,以及它们之间的区别到底是什么。

好吧,让我们从一个示例开始:

let score = 9001

我们可以这样写一个简单的条件来检查分数是否超过 9000:

if score > 9000 {
    print("It's over 9000!")
}

现在,如果我们想为等于或低于 9000 的分数打印不同的信息,我们可以这样写:

if score > 9000 {
    print("It's over 9000!")
}

if score <= 9000 {
    print("It's not over 9000!")
}

这完全没问题,你的代码也会完全按照您的预期运行。但现在我们给 Swift 增加了工作:它需要两次检查 score 的值。对于一个简单的整数,这样做的速度非常快,但如果我们的数据更复杂,速度就会更慢。

这就是 else 的作用所在,因为它意味着 “如果我们检查的条件不为真,则运行这段代码”。

因此,我们可以将之前的代码重写成这样:

if score > 9000 {
    print("It's over 9000!")
} else {
    print("It's not over 9000!")
}

有了这一改动,Swift 只需检查一次分数,而且我们的代码更简短、更易读。

现在想象一下,我们需要三条消息:分数超过 9000 时一条,正好 9000 时一条,低于 9000 时一条。我们可以这样写:

if score > 9000 {
    print("It's over 9000!")
} else {
    if score == 9000 {
        print("It's exactly 9000!")
    } else {
        print("It's not over 9000!")
    }
}

同样,这样做也没有问题,就像你希望的那样。不过,我们可以通过使用 else if 来使代码更易于阅读,它可以让我们将 else 与后面的 if 直接结合起来,就像这样:

if score > 9000 {
    print("It's over 9000!")
} else if score == 9000 {
    print("It's exactly 9000!")
} else {
    print("It's not over 9000!")
}

为了尝试这个方法,我想使用一个 Swift 函数 print():在运行该函数时输入一些文本,然后将其打印出来。

这让我们的代码更容易阅读和理解,因为我们不再需要嵌套的条件,而是有一个可以向下阅读的流程。

你可以有任意多的 else if 检查,但你需要的是一个 if 和零个或一个 else

如何检查多个条件

Swift 为我们提供了 && 和 || 来同时检查多个条件,当只使用两个条件时,它们就非常简单了。

举个例子,假设我们在运行一个论坛,用户可以在论坛上发布消息,也可以删除他们拥有的任何消息。我们可以这样编写代码:

if isOwner == true || isAdmin == true {
    print("You can delete this post")
}

当我们要检查几件事时,情况就会变得混乱。例如,我们可以说普通用户只有在我们允许的情况下才能删除消息,但管理员却可以随时删除帖子。我们可以这样编写代码:

if isOwner == true && isEditingEnabled || isAdmin == true {
    print("You can delete this post")
}

但这是要检查什么呢?&& 和 || 检查的执行顺序是什么?可能是这个意思:

if (isOwner == true && isEditingEnabled) || isAdmin == true {
    print("You can delete this post")
}

这句话的意思是 “如果是所有者,并且编辑功能已启用,你可以删除帖子;如果你是管理员,即使您不是帖子的所有者,您也可以删除帖子”。这很有道理:如果允许编辑,用户可以删除自己的帖子,但管理员总是可以删除帖子。

不过,你也可以这样理解:

if isOwner == true && (isEditingEnabled || isAdmin == true) {
    print("You can delete this post")
}

现在,它的意思完全不同了:”启用了编辑功能或者你是管理员这两个条件任意一个成立,并且你是贴子的所有者,那么你才可以删除帖子”。这意味着管理员不能删除他们不拥有的帖子,这就说不通了。

显然,Swift 不喜欢这种模棱两可的说法,所以它总是按照我们这样写来解释代码:

if (isOwner == true && isEditingEnabled) || isAdmin == true {
    print("You can delete this post")
}

不过,老实说,让 Swift 来解决这个问题并不是一种好的体验,所以我们可以自己插入括号来明确我们的意思。

在这方面没有具体的建议,但实际上,只要在一个条件中混合使用 && 和 || ,就几乎肯定要使用括号来明确结果。

如何使用switch语句检查多个条件

你可以反复使用 if 和 else if 来检查各种条件,但这样读起来会有点费劲。例如,如果我们有一个来自枚举的天气预报,我们可以根据一系列条件选择要打印的信息,就像这样:

enum Weather {
    case sun, rain, wind, snow, unknown
}

let forecast = Weather.sun

if forecast == .sun {
    print("It should be a nice day.")
} else if forecast == .rain {
    print("Pack an umbrella.")
} else if forecast == .wind {
    print("Wear something warm")
} else if forecast == .snow {
    print("School is cancelled.")
} else {
    print("Our forecast generator is broken!")
}

这个方法可行,但也有问题:

  1. 尽管我们每次检查的都是同一件事,但我们还是不得不写**forecast**。
  2. 我不小心检查了两次 .rain,尽管第二次检查永远不会为真,因为只有在第一次检查失败时才会执行第二次检查。
  3. 我根本没有检查 .snow,所以我们丢失了功能。

我们可以使用一种名为 switch 的不同条件检查方法来解决上述三个问题。这同样可以让我们逐个检查单个情况,但现在 Swift 可以提供帮助。在枚举的情况下,Swift 知道枚举可能有的所有情况,因此如果我们漏掉一个或检查了两次,Swift 就会报错。

因此,我们可以用以下方法替换所有 if 和 else if 检查:

switch forecast {
case .sun:
    print("It should be a nice day.")
case .rain:
    print("Pack an umbrella.")
case .wind:
    print("Wear something warm")
case .snow:
    print("School is cancelled.")
case .unknown:
    print("Our forecast generator is broken!")
}

让我们来分析一下:

  1. 我们以 switch forecast 开始,它告诉 Swift 这是我们要检查的值。
  2. 然后,我们有一串 case 语句,每个 case 都是我们要与 forecast 进行比较的值。
  3. 我们的每个 case 都列出了一种天气类型,因为我们是根据 forecast 切换的,所以不需要写 Weather.sunWeather.rain 等,Swift 知道这一定是某种天气类型。
  4. 在每种情况后,我们都会写一个冒号,以标记如果该情况匹配,则要运行的代码的起始位置。
  5. 我们使用收尾括号来结束 switch 语句。

如果你尝试将 .snow 改为 .rain,你会发现 Swift 会出现两次警告:一次是我们检查了两次 .rain,另一次是我们的 switch 语句并不详尽——它没有处理所有可能的情况。

如果你用过其他编程语言,你可能会注意到 Swift 的 switch 语句有两处不同:

  1. 所有 switch 语句都必须是穷举性的,这意味着必须处理所有可能的值,因此不能意外遗漏。
  2. Swift 会执行与你要检查的条件相匹配的第一个 case,但不会再执行更多。其他语言通常会继续执行所有后续情况下的其他代码,这通常是完全错误的默认做法。

尽管这两种做法都是对的,但 Swift 还是在需要时为我们提供了更多的控制。

首先,所有**switch**语句都必须详尽无遗:必须确保涵盖所有可能的值。如果要在字符串上进行切换,那么显然不可能对所有可能的字符串进行穷举检查,因为字符串的数量是无限的,因此我们需要提供一个默认情况——在其他情况都不匹配时运行代码。

例如,我们可以切换包含地名的字符串:

let place = "Metropolis"

switch place {
case "Gotham":
    print("You're Batman!")
case "Mega-City One":
    print("You're Judge Dredd!")
case "Wakanda":
    print("You're Black Panther!")
default:
    print("Who are you?")
}

末尾的 default: 是默认情况,如果所有情况都不匹配,则运行默认情况。

请记住 Swift 会按顺序检查用例,并运行第一个匹配的用例。如果将 default 放在任何其他情况之前,该情况将毫无用处,因为它永远不会匹配,Swift 将拒绝构建您的代码。

其次,如果你明确希望 Swift 继续执行后续情况,请使用 fallthrough。这种方法并不常用,但有时(只是有时)可以帮助您避免重复工作。

例如,有一首著名的圣诞歌曲叫《圣诞十二日》,随着歌曲的进行,一个不幸的人身上堆满了越来越多的礼物,到了第六天,他的家里已经堆满了礼物。

我们可以用 fallthrough 简单地模拟这首歌。首先,下面是不使用 fallthrough 时的代码:

let day = 5
print("My true love gave to me…")

switch day {
case 5:
    print("5 golden rings")
case 4:
    print("4 calling birds")
case 3:
    print("3 French hens")
case 2:
    print("2 turtle doves")
default:
    print("A partridge in a pear tree")
}

这将打印出 “5 golden rings”,但这并不完全正确。第 1 天应该只打印 “A partridge in pear tree”,第 2 天应该先打印 “2 turtle doves”,然后再打印 “A partridge in a pear tree”,第 3 天应该打印 “3 French hens”、”2 turtle doves”,然后……你就明白了。

我们可以使用 fallthrough 来实现这种行为:

let day = 5
print("My true love gave to me…")

switch day {
case 5:
    print("5 golden rings")
    fallthrough
case 4:
    print("4 calling birds")
    fallthrough
case 3:
    print("3 French hens")
    fallthrough
case 2:
    print("2 turtle doves")
    fallthrough
default:
    print("A partridge in a pear tree")
}

这将与第一种情况相匹配,并打印出 “5 golden rings”,但穿透行意味着第四种情况将执行并打印出 “4 calling birds”,这反过来又使用了穿透,从而打印出 “3 French hens”,依此类推。虽然与歌曲不完全匹配,但至少可以看到功能的运行!

什么时候应该使用 switch 语句而不是 if?

Swift 开发人员可以同时使用 switch 和 if 来检查代码中的多个值,而且通常并不存在选择其中一种而非另一种的硬性理由。尽管如此,有三个原因可以让你考虑使用 switch 而不是 if:

  1. Swift 要求其 switch 语句是穷举性的,这意味着你必须为每个可能的检查值(例如枚举的所有情况)设置一个 case 块,或者你必须设置一个默认情况。而 if 和 else if 则不是这样,因此您可能会不小心漏掉一个 case
  2. 使用 switch 检查一个值是否有多个可能的结果时,该值只会被读取一次,而使用 if 则会被读取多次。当你开始使用函数调用时,这一点变得更加重要,因为其中有些函数调用可能会很慢。
  3. Swift 的 switch 的 case 允许进行高级模式匹配,而 if 则不方便。

还有一种情况,但比较模糊:一般来说,如果你想在三种或三种以上的可能状态下检查同一个值,你会发现人们更喜欢使用 switch,而不是 if,因为这样更容易辨认——我们在重复检查同一个值,而不是编写不同的条件。

PS:我之所以介绍 fallthrough 关键字,是因为它对来自其他编程语言的人来说很重要,但在 Swift 中使用它的情况却相当少见——如果你很难想出它在什么情况下可能有用,也不用担心,因为老实说,大多数情况下它都没有用!

如何使用三元条件运算符进行快速检查

在 Swift 中还有最后一种检查条件的方法,当你看到它时,很可能会想知道它什么时候有用。公平地说,在很长一段时间里,我很少使用这种方法,但正如你稍后会看到的,它在 SwiftUI 中真的很重要。

这种方法叫做三元条件运算符。要理解它为什么叫三元条件运算符,首先要知道 +、-、== 等运算符都被称为二元运算符,因为它们处理的是两部分输入:例如,2 + 5 处理的是 2 和 5。

三元运算符可以处理三个输入值,事实上,因为三元条件运算符是 Swift 中唯一的三元运算符,所以你经常会听到有人称它为 “三元运算符”。

不管怎么说,别再提它的名字了:它到底有什么作用呢?三元运算符允许我们检查一个条件,并返回两个值中的一个:条件为真时返回某值,条件为假时返回另一个值。

例如,我们可以创建一个名为 age 的常量来存储某人的年龄,然后再创建一个名为 canVote 的常量来存储此人是否可以投票:

let age = 18
let canVote = age >= 18 ? "Yes" : "No"

代码运行时,canVote 将被设置为 “Yes”,因为年龄被设置为 18 岁。

正如你所看到的,三元运算符分为三个部分:检查(age >= 18)、条件为真时(”Yes”)和条件为假时(”No”)。这使得它与普通的 if 和 else 块完全相同,顺序也一样。

  1. 我们的条件是什么?是年龄大于等于 18 岁。
  2. 条件为真时怎么办?返回 “Yes”,这样就可以存储在 canVote 中。
  3. 如果条件为假呢?返回 “No”。

我们再来看看其他例子,首先是一个简单的例子,它以 24 小时格式读取一个小时,并打印出两条信息中的一条:

let hour = 23
print(hour < 12 ? "It's before noon" : "It's after noon")

请注意,这个程序并没有将结果赋值给任何地方,而是根据 hour 的值打印出 true 或 false 的情况。

这里还有一个读取数组 count 作为条件的例子,然后返回两个字符串中的一个:

let names = ["Jayne", "Kaylee", "Mal"]   
let crewCount = names.isEmpty ? "No one" : "\(names.count) people"
print(crewCount)

当你的条件使用 == 来检查是否相等时,读起来就有点困难了,如图所示:

enum Theme {
    case light, dark
}

let theme = Theme.dark

let background = theme == .dark ? "black" : "white"
print(background)

= theme == 部分通常是人们难以读懂的部分,但要记住将其分解:

  • 条件判断是:theme == .dark
  • 真:“black”
  • 假:“white”

因此,如果 theme 等于 .dark,则返回 “black”,否则返回 “white”,然后将其赋值给 background

现在,你可能想知道三元运算符为什么有用,尤其是当我们有常规的 if/else 条件时。我知道这不是一个很好的答案:有些时候,尤其是在 SwiftUI 中,我们别无选择,必须使用三元运算符。

通过我们检查小时数的代码,你可以大致看出问题所在:

let hour = 23
print(hour < 12 ? "It's before noon" : "It's after noon")

如果我们想使用 if 和 else 来写出这些代码,我们就需要写出这样的代码:

print(
    if hour < 12 {
        "It's before noon"
    } else {
        "It's after noon"
    }
)

或者像这样运行两次 print()

if hour < 12 {
    print("It's before noon")
} else {
    print("It's after noon")
}

第二段代码在Swift可以正常工作,但在 SwiftUI 中几乎不可能,稍后你将看到这一点。所以,尽管你可能会想知道既然有了ifelse为什么还要使用三元运算符,但请相信我:对于SwiftUI它很重要!

什么时候应该在 Swift 中使用三元运算符?

三元运算符可以让我们根据条件从两个结果中选择一个,而且非常简洁:

let isAuthenticated = true
print(isAuthenticated ? "Welcome!" : "Who are you?")

有些人非常依赖三元运算符,因为它能让代码变得非常简短;而有些人则尽量避免使用三元运算符,因为它会让代码变得更难读。

我非常赞同 “尽可能避免 “的观点,因为尽管这段代码较长,但我确实觉得它更容易理解:

if isAuthenticated {
    print("Welcome")
} else {
    print("Who are you?")
}

现在,三元运算符在 SwiftUI 中得到了广泛应用。我不想在这里给出代码示例,因为这可能会让人有点不知所措,但如果你愿意,你真的可以在这里使用三元运算符。即便如此,为了让代码更容易阅读,我还是会尽可能去掉三元运算符,但你应该亲自尝试一下,然后得出自己的结论。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注