侧边栏壁纸
  • 累计撰写 28 篇文章
  • 累计创建 10 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

100天学会SwiftUI——if、switch、三目运算

Jserv
2025-05-06 / 0 评论 / 0 点赞 / 7 阅读 / 20402 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2025-05-06,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

如果说莎士比亚的《哈姆雷特》中有一句话是大多数人都知道的,那就是“存在与否,这就是问题所在。”莎士比亚的意思是,这是生死攸关的终极问题,但恰好哈姆雷特击中了编程逻辑的核心:评估一个条件是否真实。

今天,我们将进入Swift的真正细节:运算符和条件,这让我们在程序运行时评估其状态,并根据结果采取不同的行动。有几种方法可以这样做,你需要它们全部,但我们会一步一步地进行,以便你可以看到它们是如何比较的。

如何检查条件是真还是假

程序经常做出选择

  • 如果学生的考试成绩超过80分,则打印成功信息。

  • 如果用户输入的名字在朋友名字之后按字母顺序排列,请先输入朋友的名字。

  • 如果将数字添加到数组中使其包含超过3个项目,请删除最早的项目。

  • 如果用户被要求输入他们的姓名,但什么也没输入,请给他们一个默认名称“匿名”。

Swift用if语句处理这些,这让我们检查一个条件,如果条件为真,则运行一些代码。它们看起来像这样:

if someCondition {
    print("Do something")
}

让我们来分解一下:

  1. 条件以if开头,这向Swift发出信号,我们想检查代码中的某种条件。

  2. someCondition部分是你写条件的地方——分数超过80分吗?数组是否包含超过3个项目?

  3. 如果条件是真实的——如果分数真的超过80——那么我们打印“做点什么”的信息。

当然,这不是代码中的全部:我没有提到小{}符号。这些被称为牙套——更具体地说,是打开和关闭牙套——尽管有时你会听到它们被称为“大发牙套”或“大发大括号”。

这些大括号在Swift中广泛用于标记代码块:开头大括号启动块,闭合大括号结束它。代码块是我们想要运行的所有代码,如果我们的条件在检查时恰好为真,在我们的案例中,这是打印一条消息。

你可以在那里包含尽可能多的代码:

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

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

好吧,让我们试试分数示例:如果score常数超过80,让我们打印一条消息。以下是代码中的样子:

let score = 85

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

在该代码中,score > 80是我们的条件。你会记得>学校的意思是“大于”,所以我们的完整条件是“如果分数大于80”。如果它大于80,“干得好!”将被打印出来——很好!

那个>符号是一个比较运算符,因为它比较了两件事并返回一个布尔结果:左边的东西比右边的东西大吗?您还可以使用<表示小于,>=表示“大于或等于”,<=表示“小于或等于”。

让我们试试吧——你认为这个代码会打印什么?

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 eligible to vote")
}

尝试在脑海中精神上运行代码——哪些print()行将实际运行?

好吧,如果speed大于或等于88,我们的第一个将运行,因为它正好是88,firstprintprint()代码将运行。

如果percentage小于85,第二个将运行,由于它正好是85,secondprintprint()不会运行——我们使用了小于、不小于或等于。

如果age大于或等于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()countremove(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("G'day!")
}

第二个是!=,意思是“不等于”,像这样使用:

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)!")

那个""是一个空字符串:我们开始字符串并结束字符串,中间没有任何东西。通过将username与该用户名进行比较,我们正在检查用户是否也为他们的用户名输入了一个空字符串,这正是我们想要的。

现在,还有其他方法可以进行这项检查,你了解他们做什么很重要。

首先,我们可以将字符串的count(它有多少个字母)与0进行比较,如下:

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

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

在许多语言中,速度非常快,但在Swift中则不是。你看,Swift支持各种复杂的字符串——从字面上看,每一种人类语言都可以开箱即用,包括表情符号,而这在许多其他编程语言中是不正确的。然而,这种真正伟大的支持是有代价的,成本的一部分是,询问字符串的count使Swift逐一计数所有字母——它不只是将其长度与字符串分开存储。

所以,想想你拥有一串巨大的字符串来存放莎士比亚的全部作品的情况。我们对count == 0的小检查必须通过并计数字符串中的所有字母,即使我们一计算至少一个字符,我们就会知道问题的答案。

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

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

那更好,但我们可以更进一步。你看,最终重要的是你的状况必须归结为真或假;Swift不会允许其他任何东西。在我们的案例中,username.isEmpty已经是一个布尔值,这意味着它将是真或假,因此我们可以让我们的代码更简单:

if username.isEmpty {
    username = "Anonymous"
}

如何检查多种条件

当我们使用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只需要检查一次age:如果它大于或等于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")
}

There’s an even more advanced condition called else if, which lets you run a new check if the first one fails. You can have just one of these if you want, or have multiple else if, and even combine else ifwith an else if needed. However, you can only ever have one else, because that means “if all the other conditions have been false.”

看起来是这样的:

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条件,但要注意你的代码不要太复杂!

除了使用elseelse 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")
}

这将打印“您可以购买游戏”,因为尽管我们的条件的前半部分失败——用户满18岁——但后半部分通过,因为他们确实有父母的同意。

请记住,在条件中使用== true可以删除,因为我们显然已经在检查布尔值。所以,我们可以改写这个:

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

为了完成检查多个条件,让我们尝试一个更复杂的示例,该示例同时结合了ifelse ifelse||,甚至展示枚举如何适应条件。

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

  • 如果我们乘飞机或直升机去某个地方,我们会打印“让我们飞吧!”

  • 如果我们骑自行车去,我们会打印“我希望有一条自行车道......”

  • 如果我们开车去,我们会打印“是时候堵车了。”

  • 否则,我们将打印“我现在要租一辆滑板车!”

这是那个代码:

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了,因为Swift知道transport必须是某种TransportOption。因此,我们可以检查它是否等于.airplane而不是TransportOption.airplane

  3. 使用||来检查transport是等于.airplane还是等于.helicopter,如果其中任何一个都为真,则条件为真,并且“我们飞吧!”被打印出来。

  4. 如果第一个条件失败——如果运输模式不是.airplane.helicopter——那么第二个条件是运行:运输模式是.bicycle吗?如果是这样,“我希望有一条自行车道......”就打印出来了。

  5. 如果我们也不骑自行车去,那么我们检查一下我们是否开车去。如果我们是,“是时候堵车了。”就打印出来了。

  6. 最后,如果之前的所有条件都失败了,那么else块就会运行,这意味着我们乘坐滑板车去。

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

您可以重复使用ifelse 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 == .rain {
    print("School is cancelled.")
} else {
    print("Our forecast generator is broken!")
}

那有用,但有问题:

  1. 我们不得不一直写forecast,尽管我们每次都在检查同样的东西。

  2. 我不小心检查了两次.rain,尽管第二次检查永远不会是真的,因为只有当第一次检查失败时才会执行第二次检查。

  3. 我根本没有检查.snow,所以我们缺少功能。

我们可以使用一种叫做switch的不同检查条件的方法来解决这三个问题。这也让我们可以逐一检查单个案例,但现在Swift能够提供帮助。就枚数而言,它知道枚枚枚数可能存在的所有可能的情况,因此如果我们错过一个或检查两次,它就会抱怨。

因此,我们可以用这个替换所有ifelse 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. We then have a string of case statements, each of which are values we want to compare against forecast.

  3. 我们每个案例都列出了一种天气类型,由于我们正在切换forecast,我们不需要写Weather.sunWeather.rain等——Swift知道这一定是某种Weather

  4. 在每个案例之后,我们编写一个冒号来标记要运行的代码的开始,如果该案例匹配。

  5. 我们使用闭合大括号来结束switch语句。

如果你尝试将.snow更改为.rain,你会看到Swift大声抱怨:一旦我们检查了两次.rain,我们的switch语句并不详尽无遗——它不能处理所有可能的情况。

如果您曾经使用过其他编程语言,您可能已经注意到Swift的switch语句在两个地方有所不同:

  1. 所有switch语句都必须是详尽的,这意味着所有可能的值都必须在那里处理,这样您就不能意外地遗忘一个。

  2. Swift将执行第一个与您正在检查的条件匹配的案例,但不会执行更多。其他语言经常从所有后续情况下继续执行其他代码,这通常是完全错误的默认操作。

虽然这两个陈述都是正确的,但如果我们需要的话,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个金戒指”,这不太对。第1天只应打印“梨树上的鹧鸪”,第2天应该是“2只海龟鸽”,然后是“梨树上的鸷�”,第3天应该打印“3只法国母鸡”、“2只海龟鸽”,然后......好吧,你明白了。

我们可以使用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")
}

如何使用三目运算符进行快速测试

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

这个选项被称为三元条件运算符。要理解它为什么有这个名字,你首先需要知道+-==等都被称为二进制运算符,因为它们与两个输入一起使用2 + 5,例如,与2和5一起使用。

三元运算符使用三个输入,事实上,由于三元条件运算符是Swift中唯一的三元运算符,你经常会听到它被称为“三元运算符”。

总之,名字就够了:这到底有什么作用?好吧,三元运算符允许我们检查一个条件,并返回两个值之一:如果条件为真,则为假,则为假。

例如,我们可以创建一个名为age的常量来存储某人的年龄,然后创建一个名为canVote的第二个常量,该常量将存储这个人是否能够投票:

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

当该代码运行时,canVote将设置为“是”,因为age设置为18岁。

如您所见,三元运算符分为三部分:检查(age >= 18),条件为真时(“是”),条件为假时的检查(“否”)。这使得它完全像一个常规的ifelse块,顺序相同。

如果有帮助的话,Scott Michaud建议一个有用的助语:WTF。它代表“什么、真、假”,并符合我们代码的顺序:

  • 我们的状况如何?嗯,age >= 18

  • 当条件属实时该怎么办?发送回“是”,以便将其存储在canVote

  • 如果条件是错误的呢?发送回“否”。

让我们看看其他一些例子,从一个简单的例子开始,以24小时格式读取一小时,并打印两条消息中的一条:

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

请注意,这并没有将结果分配到任何地方——根据hour值,真或假情况都会被打印出来。

或者,这是一个将数组的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

  • 真实:“黑色”

  • 错误:“白色”

因此,如果主题等于.dark返回“黑色”,否则返回“白色”,然后将其分配给background

现在,你可能想知道为什么三元算子是有用的,特别是当我们有正则/else条件可用时。我知道这不是一个好答案,但你必须相信我:有些时候,特别是在SwiftUI中,我们别无选择,必须使用三元。

您可以大致查看我们代码的问题所在,以检查时间:

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

如果我们想用ifelse写出来,我们需要写这个无效代码:

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")
}

[本文翻译自hackingwithswift,点击链接阅读原文]

0
  1. 支付宝打赏

    qrcode alipay
  2. 微信打赏

    qrcode weixin

评论区