Skip to content

第2天 布尔值、字符串插值

林奇定律说:“当事情变得棘手时,所有人都会离开。” 任何人都能完成课程的第一天,但只有勤奋的人才能回来参加第二天的学习 —— 坚持下来,你真棒!

昨天我们开始学习了简单数据类型 —— 那些只能存储一个值的数据类型,比如一个数字或一个字符串。今天我们将继续学习,探索如何用布尔值存储真假信息,以及如何通过插值来构建字符串。在某些时候,你可能会想 “我真的需要知道这些吗?” 答案是“是的”—— 如果这些内容出现在这门课程中,那你绝对需要掌握!

不过今天有件重要的事,因为你将迎来第一个 checkpoint(检测点)。我们会在这里暂停一下,让你自己编写一些代码,确保你已经完全理解了所学的内容。一开始面对空白的代码界面可能会有些困难,但你会有足够的时间,而且我也会提供一些提示。

今天你有两个新的教程要学习,还有一个总结和一个检测点要完成。 和之前一样,如果你想更深入地了解每个主题,有一些可选的扩展阅读,但除非你自己想读,否则不需要看。

2.1 如何用布尔值存储真假信息

作者:Paul Hudson 2021 年 10 月 25 日 已更新至 Xcode 16.4

到目前为止,我们已经学习了字符串、整数和小数,但还有第四种数据类型已经悄悄出现过了:一种非常简单的类型,叫做布尔值(Boolean),它只能存储 true(真)或 false(假)。如果你好奇的话,布尔值是以英国数学家乔治・布尔(George Boole)的名字命名的,他花了大量时间研究和撰写有关逻辑的内容。

我说布尔值是悄悄出现的,是因为你已经见过它几次了:

swift
let filename = "paris.jpg"
print(filename.hasSuffix(".jpg"))

let number = 120
print(number.isMultiple(of: 3))

hasSuffix()isMultiple(of:) 都会根据它们的检查返回一个新值:字符串要么有这个后缀,要么没有;120 要么是 3 的倍数,要么不是。在这两种情况下,答案都只有简单的真或假,这就是布尔值的用武之地 —— 它们只存储这种信息,仅此而已。

创建布尔值和创建其他数据类型一样,只不过你应该给它赋一个初始值 truefalse,就像这样:

swift
let goodDogs = true
let gameOver = false

你也可以通过其他代码给布尔值赋初始值,只要最终结果是 truefalse 就行:

swift
let isMultiple = 120.isMultiple(of: 3)

和其他数据类型不同,布尔值没有 +- 这样的算术运算符 —— 毕竟,true + true 应该等于什么呢?不过,布尔值有一个特殊的运算符 !,它的意思是 “非”。它可以把布尔值从 true 变成 false,或者从 false 变成 true

例如,我们可以这样反转一个布尔值:

swift
var isAuthenticated = false
isAuthenticated = !isAuthenticated
print(isAuthenticated)
isAuthenticated = !isAuthenticated
print(isAuthenticated)

运行这段代码会先打印 “true”,然后打印 “false”,因为 isAuthenticated 一开始是 false,我们把它设为 “非 false”,也就是 true,然后再反转一次,它又变回 false 了。

布尔值还有一些额外的实用功能。特别是,如果你对一个布尔值调用 toggle() 方法,它会把 true 变成 false,把 false 变成 true。要试试这个的话,可以把 gameOver 设为变量,然后像这样修改它:

swift
var gameOver = false
print(gameOver)

gameOver.toggle()
print(gameOver)

这段代码会先打印 false,调用 toggle() 之后会打印 true。是的,这和使用 ! 的效果一样,只是代码更简洁一些,但在处理复杂代码时,这个方法出奇地有用!

【练习题】双精度浮点数和布尔值

第 1/6 题:以下哪行代码创建了布尔值?

选项 1:

swift
var animated = false

选项 2:

swift
var isLoaded = 1

第 2/6 题:以下哪行代码创建了布尔值?

选项 1:

swift
var dressHasPockets = true

选项 2:

swift
var zoomed = 0

第 3/6 题:以下哪行代码创建了布尔值?

选项 1:

swift
var isReady = false

选项 2:

swift
var isEnabled = 0.0

第 4/6 题:以下哪行代码创建了布尔值?

选项 1:

swift
var isEncrypted = true

选项 2:

swift
var isHidden = "yes"

第 5/6 题:以下哪行代码创建了布尔值?

选项 1:

swift
var sorted = "false"

选项 2:

swift
var isVisible = false

第 6/6 题:以下哪行代码创建了布尔值?

选项 1:

swift
var isSaved = "true"

选项 2:

swift
var loggedIn = true

2.2 如何拼接字符串

作者:Paul Hudson 2021 年 10 月 25 日 已更新至 Xcode 16.4

Swift 给了我们两种拼接字符串的方法:使用 + 运算符,以及一种叫做 “字符串插值” 的特殊技巧,它可以把任何类型的变量直接放到字符串里面。

我们先从更简单的方法开始,也就是用 + 来拼接字符串:当你有两个字符串时,只需用 + 就能把它们拼接成一个新的字符串,就像这样:

swift
let firstPart = "Hello, "
let secondPart = "world!"
let greeting = firstPart + secondPart

如果需要,你可以多次拼接:

swift
let people = "Haters"
let action = "hate"
let lyric = people + " gonna " + action
print(lyric)

运行这段代码会打印 “Haters gonna hate”—— 没错,我是泰勒・斯威夫特的忠实粉丝,而且我觉得她的歌词很适合作为 Swift 编程教程的例子!

注意,我们用 + 来拼接两个字符串,但当我们处理 IntDouble 时,+ 是用来做加法的。这叫做 “运算符重载”—— 同一个运算符(比如 +)可以根据使用场景有不同的含义。对于字符串来说,+= 也适用,它可以把一个字符串直接添加到另一个字符串后面。

这种方法在处理简单情况时很好用,但你不会想过多地使用它。因为每次 Swift 看到用 + 拼接两个字符串时,都必须先把它们拼成一个新的字符串,然后才能继续,如果要拼接很多内容,就会很浪费资源。

想想这个例子:

swift
let luggageCode = "1" + "2" + "3" + "4" + "5"

Swift 不能一次性把所有这些字符串都拼起来。相反,它会先把前两个拼起来得到 “12”,然后把 “12” 和 “3” 拼起来得到 “123”,接着把 “123” 和 “4” 拼起来得到 “1234”,最后把 “1234” 和 “5” 拼起来得到 “12345”—— 它会创建 “12”、“123” 和 “1234” 这些临时字符串,即使代码最终运行完之后根本用不到它们。

Swift 有一种更好的方法,叫做 “字符串插值”,它能让我们高效地用其他字符串、整数、小数等创建新的字符串。

如果你还记得,之前我说过,你可以在字符串中包含双引号,只要在双引号前面加一个反斜杠,让 Swift 知道要特殊处理它们:

swift
let quote = "Then he tapped a sign saying \"Believe\" and walked away."

字符串插值也用到了类似的语法:在字符串里面写一个反斜杠,然后把变量或常量的名字放在括号里。

例如,我们可以创建一个字符串常量和一个整数常量,然后把它们组合成一个新的字符串:

swift
let name = "Taylor"
let age = 26
let message = "Hello, my name is \(name) and I'm \(age) years old."
print(message)

运行这段代码会打印 “Hello, my name is Taylor and I'm 26 years old.”

字符串插值比一次次用 + 拼接字符串高效得多,而且还有另一个重要的好处:你可以直接插入整数、小数等,不需要额外的操作。

你看,用 + 可以把字符串和字符串相加、整数和整数相加、小数和小数相加,但不能把整数和字符串相加。所以,下面这种代码是不允许的:

swift
let number = 11
let missionMessage = "Apollo " + number + " landed on the moon."

你当然可以让 Swift 把数字当作字符串来处理,就像这样:

swift
let missionMessage = "Apollo " + String(number) + " landed on the moon."

但使用字符串插值仍然更快,而且可读性更好:

swift
let missionMessage = "Apollo \(number) landed on the moon."

提示: 你也可以在字符串插值中进行计算。例如,下面的代码会打印 “5 x 5 is 25”:

swift
print("5 x 5 is \(5 * 5)")

【可选阅读】为什么 Swift 要有字符串插值?

作者:Paul Hudson 2020 年 5 月 28 日 已更新至 Xcode 16.4

当需要向用户展示信息时 —— 无论是打印出来的消息、按钮上的文字,还是任何与你的应用相关的内容 —— 你通常都会大量使用字符串。

当然,我们不只是想要静态的字符串,因为我们想向用户展示一些他们能用的相关数据。所以,Swift 给我们提供了字符串插值,作为一种在运行时把自定义数据注入字符串的方式:它会用我们提供的数据替换字符串中的一个或多个部分。

例如:

swift
var city = "Cardiff"
var message = "Welcome to \(city)!"

当然,在这个简单的例子中,我们本可以直接把城市名写到字符串里 ——“Welcome to Cardiff!”—— 但在实际应用中,动态插入数据很重要,因为这能让我们展示真实的用户数据,而不是我们自己输入的内容。

Swift 能够把任何类型的数据放到字符串插值中。结果可能并不总是有用,但对于 Swift 的所有基本类型 —— 字符串、整数、布尔值等 —— 效果都很好。

【练习题】字符串插值

第 1/6 题:以下哪行代码使用了字符串插值?

选项 1:

swift
var name = "\(firstName) \(lastName)"

选项 2:

swift
var versionString = "You're using v(version)"

第 2/6 题:以下哪行代码使用了字符串插值?

选项 1:

swift
var alert = "Error: \(message)!"

选项 2:

swift
var message = "Installation failed: \{reason}."

第 3/6 题:以下哪行代码使用了字符串插值?

选项 1:

swift
var forecast = "Today's weather will be \(weather)"

选项 2:

swift
var formattedHeight = "You are (size)cm"

第 4/6 题:以下哪行代码使用了字符串插值?

选项 1:

swift
var result = "\(daysRemaining) days to go"

选项 2:

swift
var engine = "Your engine is (size)cc"

第 5/6 题:以下哪行代码使用了字符串插值?

选项 1:

swift
var str = "Hello, playground!"

选项 2:

swift
var warning = "You need to be \(years) or older"

第 6/6 题:以下哪行代码使用了字符串插值?

选项 1:

swift
var error = "Error, please try again."

选项 2:

swift
var greeting = "Hello, \(name)!"

2.3 总结:简单数据

作者:Paul Hudson 2021 年 10 月 1 日 已更新至 Xcode 16.4

在前几章中,我们已经学习了很多关于数据基础的知识,现在来回顾一下:

  • Swift 允许我们用 let 创建常量,用 var 创建变量。
  • 如果你不打算修改一个值,一定要用 let,这样 Swift 可以帮你避免错误。
  • Swift 的字符串包含文本,从短字符串到整部小说都可以。它们能很好地支持表情符号和任何世界语言,还有一些实用的功能,比如 countuppercased()
  • 你可以用双引号来创建字符串,但如果你的字符串要跨多行,就需要用三个双引号来开头和结尾。
  • Swift 把整数叫做 “integers”,它们可以是正数或负数。它们也有一些实用的功能,比如 isMultiple(of:)
  • 在 Swift 中,小数叫做 Double,是 “双精度浮点数” 的缩写。这意味着它们可以存储非常大的数字,但它们并不总是 100% 精确 —— 当需要 100% 精确时(比如处理金钱时),你不应该使用它们。
  • 有很多内置的算术运算符,比如 +-*/,还有一些特殊的复合赋值运算符,比如 +=,可以直接修改变量。
  • 你可以用布尔值来表示简单的真或假状态,使用 ! 运算符或调用 toggle() 方法可以反转它的值。
  • 字符串插值让我们能够以一种简洁高效的方式把常量和变量放入字符串中。

内容很多,对吧?没关系 —— 在你开发应用的过程中,你会一次又一次地用到上面列出的所有内容,直到最后不用再参考这里也能完全理解。

2.4 检测点 1

作者:Paul Hudson 2021 年 10 月 1 日 已更新至 Xcode 16.4

你已经掌握了足够的知识来编写你的第一段有用的代码了,虽然相当简单:我们要把温度从摄氏度转换成华氏度。

你的目标是编写一个 Swift playground,实现以下功能:

  1. 创建一个常量,存储任意摄氏度的温度。
  2. 把它转换成华氏度,转换公式是:乘以 9,除以 5,然后加 32
  3. 向用户打印结果,同时显示摄氏度和华氏度的值。

解决这个问题所需的知识你已经都掌握了,但如果你需要一些提示,下面会给出一些。

注意: 我真的鼓励你在看任何提示或我的解决方案之前,先尝试自己构建这个 playground。我知道这看起来可能很简单,但课程很快就会变难,确保你掌握了所有基础知识是很重要的。

现在就请尝试构建这个 playground 吧。

这里有一些提示:

  1. let 来创建常量。你可以给它起任何名字,但我觉得 celsius 是个合适的名字。
  2. 摄氏度通常用小数来存储,所以一定要把它创建成小数。这可能意味着要在末尾加上 .0—— 例如,用 25.0 而不是 25
  3. 我们用 * 表示乘法,用 / 表示除法。
  4. \(someVariable) 来启用字符串插值。
  5. 如果你想让 print() 输出得更花哨一些,可以按 Option+Shift+8 得到度数符号:°。这样你就可以写出像 25°F 这样的内容了。

本站使用 VitePress 制作