IOS18 编程初学者指南(一)

原文:zh.annas-archive.org/md5/c79b480579d21d3ef3e2083c44cdee36

译者:飞龙

协议:CC BY-NC-SA 4.0

前言

欢迎来到 iOS 18 编程入门。这本书是 iOS 编程入门 系列的第九版,已经完全更新以适应 iOS 18、macOS 15.0 Sequioa 和 Xcode 16。

在这本书中,你将构建一个名为 JRNL 的日记应用。你将从探索 Xcode 开始,这是苹果的编程环境,也被称为其 集成开发环境IDE)。接下来,你将学习 Swift 的基础知识,Swift 是用于 iOS 应用的编程语言,并了解它是如何用于完成常见的编程任务的。

在你熟练掌握 Swift 的基础知识后,你将开始创建 JRNL 应用的用户界面。在这个过程中,你将使用故事板,并通过 segues 连接应用场景。

在完成用户界面后,你将添加代码来实现应用的功能。首先,你将学习如何使用表格视图显示数据。接下来,你将学习如何向应用中添加数据,以及如何在视图控制器之间传递数据。之后,你将学习如何确定设备位置并在地图上显示注释。然后,你将学习如何使用 JSON 文件持久化应用数据,创建自定义视图,并从相机或照片库添加照片。最后,你将通过实现集合视图来替代表格视图,使你的应用能够在具有更大屏幕的设备上运行,例如 iPad 或 Mac。

你现在拥有了一个完整的应用,但如何添加最新的 iOS 18 功能呢?你将从学习 SwiftData 开始,它允许你使用常规 Swift 代码描述数据模型并操作模型实例。接下来,你将学习如何使用 SwiftUI 开发应用,这是一种为所有苹果平台开发应用的全新方法。之后,你将学习如何使用 Swift Testing 测试你的代码,以及如何将苹果智能功能引入你的应用。

最后,你将学习如何使用内部和外部测试人员测试你的应用,并将其发布到 App Store。

本书面向对象

本书针对那些具有最少编码经验、新接触 Swift 和 iOS 应用开发领域的人士。建议具备基本的编程概念理解。

本书涵盖内容

第一章探索 Xcode,带你游览 Xcode,并讨论了你在本书中将使用的所有不同部分。

第二章简单值和类型,讨论了 Swift 语言如何实现值和类型。

第三章条件语句和可选类型,展示了如何实现 ifswitch 语句,以及如何实现可能或可能没有值的变量。

第四章范围运算符和循环,展示了如何在 Swift 中处理范围以及循环的不同实现方式。

第五章集合类型,涵盖了常见的集合类型,包括数组、字典和集合。

第六章函数和闭包,涵盖了如何使用函数和闭包将指令分组在一起。

第七章类、结构和枚举,讨论了在 Swift 中表示包含状态和行为复杂对象的方法。

第八章协议、扩展和错误处理,讨论了创建复杂数据类型可以采用的协议,扩展现有类型的特性,以及如何在代码中处理错误。

第九章Swift 并发,介绍了并行和异步编程的概念,并展示了您如何在应用中实现它们。

第十章设置用户界面,涉及创建JRNL应用并设置用户将看到的初始屏幕。

第十一章构建用户界面,涵盖了为JRNL应用设置主屏幕。

第十二章完成用户界面设置,涵盖了为JRNL应用设置剩余的屏幕。

第十三章修改应用屏幕,是关于在故事板中配置应用的每个屏幕。

第十四章开始使用 MVC 和表格视图,涵盖了与表格视图一起工作以及如何使用它来显示项目列表。

第十五章将数据添加到表格视图中,涉及使用数组作为数据源将数据合并到表格视图中。

第十六章在视图控制器之间传递数据,教您如何将使用视图控制器输入的数据添加到数组中,以及如何将数据从数组传递到另一个视图控制器。

第十七章开始使用 Core Location 和 MapKit,涉及使用 Core Location 和 MapKit 确定您的设备位置并在地图上添加注释。

第十八章开始使用 JSON 文件,涉及学习如何使用 JSON 文件存储和检索用户数据。

第十九章开始使用自定义视图,教您如何创建和使用一个显示星级评分的自定义视图。

第二十章开始使用相机和照片库,讨论了如何将相机或照片库中的照片添加到您的应用中。

第二十一章开始使用搜索,教您如何为主屏幕实现搜索栏。

第二十二章开始使用集合视图,展示了如何实现集合视图以替代表格视图,以适应具有更大屏幕的设备,如 Mac 或 iPad。

第二十三章开始使用 SwiftData,涉及实现 Apple 的新 SwiftData 框架以在您的应用中持久化数据。

第二十四章开始使用 SwiftUI,介绍了使用 Apple 的新 SwiftUI 技术构建应用。

第二十五章开始使用 Swift 测试,教您如何使用 Swift 测试来测试您的代码。

第二十六章开始使用 Apple 智能功能,展示了如何将 Apple 智能功能添加到您的应用中。

第二十七章测试并将您的应用提交到 App Store,涉及如何测试并将您的应用提交到 App Store。

为了充分利用这本书

本书已完全修订以适应 iOS 18、macOS 15.0 Sequioa、Xcode 16 和 Swift 6。本书的 第四部分 还涵盖了 Apple 在 2024 年 WWDC 上推出的最新技术,包括 SwiftData、SwiftUI、Swift 测试和 Apple 智能技术。

要完成本书中的所有练习,您将需要:

  • 运行 macOS 14.0 Sonoma、macOS 15.0 Sequioa 或更高版本的 Mac 计算机

  • Xcode 16.0 或更高版本

要检查您的 Mac 是否支持 macOS 15.0 Sequioa,请查看此链接:www.apple.com/my/macos/macos-sequoia-preview/。如果您的 Mac 支持,您可以通过 系统偏好设置 中的 软件更新 来更新 macOS。

要获取 Xcode 的最新版本,您可以从 Apple App Store 下载。大多数练习可以在没有 Apple 开发者账户的情况下完成,并使用 iOS 模拟器。如果您希望在实际的 iOS 设备上测试您正在开发的 App,您将需要一个免费或付费的 Apple 开发者账户。

以下章节需要付费的 Apple 开发者账户:第二十七章测试并将您的 App 提交到 App Store。如何获取付费 Apple 开发者账户的说明已包含在内。

下载示例代码文件

您可以从 GitHub 下载本书的示例代码文件 github.com/PacktPublishing/iOS-18-Programming-for-Beginners-Ninth-Edition。如果代码有更新,它将在 GitHub 仓库中更新。

我们还提供其他来自我们丰富的图书和视频目录的代码包,可在 github.com/PacktPublishing/ 获取。查看它们!

代码实战

访问以下链接查看代码运行的视频:

www.youtube.com/playlist?list=PLeLcvrwLe185EJSoURfHhSHfbPFkiZl6m

下载彩色图像

我们还提供了一份包含本书中使用的截图/图表彩色图像的 PDF 文件。您可以从这里下载:packt.link/gbp/9781836204893

使用的约定

本书使用了多种文本约定。

CodeInText:表示文本中的代码词汇、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 账号。以下是一个示例:“所以,这是一个非常简单的函数,名为 serviceCharge()。”

代码块设置为以下格式:

class ClassName {
   property1
   property2
   property3
   method1() {
      code
   }
   method2() {
      code
   }
} 

当我们希望您注意代码块中的特定部分时,相关的行或项目将以粗体显示:

let cat = Animal()
**cat.****name****=****"****Cat"**
**cat.****sound****=****"Mew"**
**cat.****numberOfLegs****=****4**
**cat.****breathesOxygen****=****true**
print(cat.name) 

粗体:表示新术语、重要词汇或屏幕上看到的词汇。例如,菜单或对话框中的词汇在文本中显示如下。以下是一个示例:“启动 Xcode 并点击 创建一个新的 Xcode 项目:”

重要提示

显示如下。

提示

显示如下。

联系我们

我们始终欢迎读者的反馈。

一般反馈: 如果你对这本书的任何方面有疑问,请在邮件主题中提及书名,并通过客户关怀@packtpub.com 给我们发邮件。

勘误: 尽管我们已经尽一切努力确保内容的准确性,但错误仍然可能发生。如果你在这本书中发现了错误,我们将不胜感激,如果你能向我们报告这一点。请访问www.packtpub.com/support/errata,选择你的书籍,点击勘误提交表单链接,并输入详细信息。

盗版: 如果你在互联网上以任何形式遇到我们作品的非法副本,如果你能提供位置地址或网站名称,我们将不胜感激。请通过版权@packt.com 与我们联系,并提供材料的链接。

如果你有兴趣成为作者: 如果你有一个你擅长的主题,并且你对撰写或为书籍做出贡献感兴趣,请访问authors.packtpub.com

留下评论!

感谢您从 Packt Publishing 购买这本书——我们希望您喜欢它!您的反馈对我们来说是无价的,它帮助我们改进和成长。一旦您阅读完毕,请花一点时间在亚马逊上留下评论;这只需一分钟,但对像您这样的读者来说意义重大。

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_QR.png

packt.link/r/1836204892

扫描下面的二维码或访问链接以获得你选择的免费电子书。

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/review_4.png

packt.link/NzOWQ

下载这本书的免费 PDF 副本

感谢您购买这本书!

你喜欢在路上阅读,但无法携带你的印刷书籍到处走?

你的电子书购买是否与你的选择设备不兼容?

别担心,现在每购买一本 Packt 书籍,你都可以免费获得该书的 DRM 免费 PDF 版本。

在任何地方、任何设备上阅读。直接从你喜欢的技术书籍中搜索、复制和粘贴代码到你的应用程序中。

优惠不会就此停止,你还可以获得独家折扣、时事通讯和每日免费内容的邮箱访问权限。

按照以下简单步骤获取这些好处:

  1. 扫描下面的二维码或访问以下链接:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_Free_PDF_QR.png

packt.link/free-ebook/9781836204893

  1. 提交你的购买证明。

  2. 就这些!我们将直接将你的免费 PDF 和其他好处发送到你的邮箱。

第一部分

Swift

欢迎来到本书的第一部分。在本部分,你将首先探索 Xcode,这是苹果的编程环境,也被称为集成开发环境IDE)。之后,你将开始学习 Swift 6 的基础知识,这是 iOS 应用程序中使用的编程语言,并了解它是如何用于完成常见编程任务的。

本部分包括以下章节:

  • 第一章探索 Xcode

  • 第二章简单值和类型

  • 第三章条件语句和可选类型

  • 第四章范围操作符和循环

  • 第五章集合类型

  • 第六章函数和闭包

  • 第七章类、结构和枚举

  • 第八章协议、扩展和错误处理

  • 第九章Swift 并发

在本部分的结尾,你将了解创建应用程序并在模拟器或设备上运行的过程,并且你将具备使用 Swift 编程语言完成常见编程任务的实际知识。这将为你学习下一章做好准备,并使你能够创建自己的 Swift 程序。让我们开始吧!

第一章:探索 Xcode

欢迎来到 iOS 18 编程入门。我希望你会发现这是一本关于在 App Store 上创建和发布 iOS 18 应用的有用介绍。

在本章中,你将在你的 Mac 上下载并安装 Xcode。然后,你将探索 Xcode 用户界面。之后,你将创建你的第一个 iOS 应用 并在 模拟器 中运行它。最后,你将在 iOS 设备 上运行你的应用。

到本章结束时,你将了解如何创建 iOS 应用,如何在模拟器中运行它,以及如何在 iOS 设备上运行它。

本章将涵盖以下主题:

  • 从 App Store 下载并安装 Xcode

  • 探索 Xcode 用户界面

  • 在模拟器中运行你的应用

  • 在 iOS 设备上运行你的应用

技术要求

要完成本章的练习,你需要以下内容:

  • 运行 macOS 14 Sonoma 或 macOS 15 Sequoia 的 Apple Mac 计算机(Apple Silicon 或 Intel)

  • Apple 账户(如果你没有,你将在本章中创建一个)

  • 可选,运行 iOS 18 的 iOS 设备

本章的 Xcode 项目位于本书代码包的 Chapter01 文件夹中,可以在此处下载:

github.com/PacktPublishing/iOS-18-Programming-for-Beginners-Ninth-Edition

查看以下视频,看看代码的实际运行情况:

youtu.be/g3mNosIoR8E

在下一节中,你将开始从 App Store 下载 Xcode,这是苹果为开发 iOS 应用而提供的 集成开发环境IDE)。

下载的总大小非常大(Xcode 为 2.98 GB,iOS 18 模拟器为 8.36 GB),因此下载可能需要一些时间。在下载之前,请确保你有足够的磁盘空间。

从 App Store 下载并安装 Xcode

Xcode 是苹果为开发 macOS、iOS、iPadOS、watchOS、tvOS 和 visionOS 应用而提供的 IDE。在编写你的第一个应用之前,你需要在你的 Mac 上下载并安装 Xcode。按照以下步骤操作:

  1. 在你的 Mac 上,从 Apple 菜单中选择 App Store

  2. 在右上角的搜索框中,输入 Xcode 并按 回车 键。

  3. 你会在搜索结果中看到 Xcode。点击 获取 然后点击 安装

  4. 如果你有一个 Apple 账户,请在文本框中输入它,并在提示时输入你的密码。如果没有,点击 创建 Apple 账户 按钮,按照逐步说明创建一个:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_01.png

图 1.1:创建 Apple 账户对话框

你可以通过此链接了解如何使用此链接创建 Apple 账户的更多信息:https://support.apple.com/en-us/108647#appstore。

  1. 一旦 Xcode 安装完成,启动它。你会看到一个许可协议屏幕。点击 同意

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_02.png

图 1.2:许可协议屏幕

  1. 你将被提示输入你的 Mac 的管理员 用户名密码。一旦完成,点击 确定

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_03.png

图 1.3:提示输入管理员用户名和密码

  1. 您将看到一个显示可用的开发平台的屏幕。现在您只需要 macOS 和 iOS。勾选 iOS 18.0,取消勾选所有其他选项,并点击 下载并安装

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_04.png

图 1.4:开发平台屏幕

  1. Xcode 将提示您重新启动以使用更新的框架。点击 重新启动 Xcode

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_05.png

图 1.5:重新启动 Xcode 提示

  1. 您将看到一个 Xcode 新功能 屏幕。点击 继续

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_06.png

图 1.6:Xcode 新功能屏幕

  1. 您将看到 欢迎使用 Xcode 屏幕。在左侧面板中点击 创建新项目…

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_07.png

图 1.7:欢迎使用 Xcode 屏幕

  1. Xcode 将自动开始下载 iOS 18.0 模拟器。请注意,在此过程完成之前,您将无法在模拟器上运行任何应用程序:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_08.png

图 1.8:模拟器下载进度条

  1. 您将看到以下新项目屏幕。在 为您的项目选择模板 部分,选择 iOS。然后选择 应用程序 并点击 下一步

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_09.png

图 1.9:新项目屏幕

  1. 您将看到 为您的项目选择选项 屏幕:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_10.png

图 1.10:为您的项目选择选项屏幕

按以下选项进行配置:

  • 产品名称:您的应用程序的名称。在文本框中输入 JRNL

  • 组织标识符:用于在 App Store 上为您的应用程序创建一个唯一的标识符。现在输入 com.myname。这被称为反向域名命名格式,是 iOS 开发者常用的格式。

  • 界面:创建应用程序用户界面的方法。将其设置为 Storyboard

  • 测试系统:您将使用的测试系统。您将在 第二十五章Swift 测试入门 中了解它。现在将其设置为

将其他设置保留为默认值。完成后点击 下一步

  1. 您将看到一个 保存 对话框。选择一个位置来保存您的项目,例如 桌面文档 文件夹,然后点击 创建

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_11.png

图 1.11:保存对话框

  1. 您将看到一个显示 Git 仓库创建失败 的对话框。点击 修复

    您看到此对话框的原因是因为在 保存 对话框中勾选了 源代码控制 复选框。Apple 建议开启 源代码控制源代码控制 不在本书的范围之内,但如果您想了解更多关于版本控制和 Git 的信息,请参阅此链接:git-scm.com/video/what-is-version-control

  2. 您将看到以下 源代码控制 屏幕:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_12.png

图 1.12:源代码控制首选项屏幕

输入以下信息:

  • 作者姓名:您的名字

  • 作者电子邮件:您的电子邮件地址

完成后,通过点击左上角的关闭按钮关闭 源代码控制 屏幕。Xcode 主窗口将出现。

太棒了!您现在已经成功下载并安装了 Xcode,并创建了您的第一个项目。在下一节中,您将了解 Xcode 用户界面。

探索 Xcode 用户界面

您已经成功创建了您的第一个 Xcode 项目!如您所见,Xcode 用户界面被分为几个不同的部分,如下所示:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_13.png

图 1.13:Xcode 用户界面

让我们更详细地看看每一部分。以下描述对应于前面截图中的数字:

  • 工具栏(1):用于构建和运行您的应用程序,并查看运行任务的进度。

  • 导航器区域(2):提供快速访问项目各个部分。默认显示 项目导航器

  • 编辑区域(3):允许您编辑源代码、用户界面和其他资源。

  • 检查器区域(4):允许您查看和编辑 导航器区域编辑区域 中选定项的信息。

  • 调试区域(5) – 包含 调试栏变量视图控制台。通过按 Shift + Command + Y 切换 调试区域

接下来,让我们更仔细地检查工具栏。工具栏的左侧如下所示:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_14.png

图 1.14:Xcode 工具栏(左侧)

让我们更详细地看看每一部分。以下描述对应于前面截图中的数字:

  • 导航器按钮(1) – 用于显示和隐藏导航器区域。

  • 停止按钮(2) – 仅在应用程序运行时出现在运行按钮旁边。停止当前运行的应用程序。

  • 运行按钮(3) – 用于构建和运行您的应用程序。

  • 方案菜单(4) – 显示构建您的项目 (JRNL) 的特定方案以及运行您的应用程序的目标设备(iPhone SE(第 3 代)。方案和目标不同。方案指定构建和运行项目设置。目标指定应用程序的安装位置,并存在于模拟器和物理设备上。

  • 活动视图(5) – 显示运行任务的进度。

工具栏的右侧如下所示:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_15.png

图 1.15:Xcode 工具栏(右侧)

让我们更详细地看看每一部分。以下描述对应于前面截图中的数字:

  • Xcode Cloud 按钮(1) – 允许您登录到 Xcode Cloud,这是一个集成到 Xcode 中的持续集成和交付服务。

  • 图书馆按钮(2) – 显示用户界面元素、代码片段和其他资源。

  • 检查器按钮(3) – 用于显示和隐藏检查器区域。

不要被所有不同的部分吓到,因为你在接下来的章节中会详细了解它们。现在,你已经熟悉了 Xcode 界面,你将在模拟器中运行你刚刚创建的应用,它将显示 iOS 设备的表示。

在模拟器中运行你的应用

模拟器是在安装 Xcode 后下载和安装的。它提供了一个模拟的 iOS 设备,这样你就可以看到你的应用看起来如何以及它的行为,而无需物理 iOS 设备。它可以模拟 iPad 和 iPhone 的所有屏幕尺寸和分辨率,这样你就可以轻松地在多个设备上测试你的应用。

要在模拟器中运行你的应用,请按照以下步骤操作:

  1. 点击目标弹出菜单以查看模拟设备的列表。从该菜单中选择iPhone SE(第 3 代)

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_16.png

图 1.16:Xcode 目标弹出菜单,已选择 iPhone SE(第 3 代)

在你自己的项目中,你应该选择你需要的任何模拟器。话虽如此,如果你想与本书中的截图完全匹配,请使用**iPhone SE(第 3 代)**模拟器。这个模拟器还有一个主页按钮,因此更容易回到主页。

  1. 点击运行按钮来在当前选定的模拟器上安装和运行你的应用。你也可以使用Command + R键盘快捷键。

  2. 模拟器将启动并显示 iPhone SE(第 3 代)的表示。你的应用显示一个空白屏幕,因为你还没有向项目中添加任何内容:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_17.png

图 1.17:模拟器显示你的应用

  1. 切换回 Xcode,点击停止按钮(或按Command + .)来停止当前运行的项目。

你刚刚在模拟器中创建并运行了你的第一个 iOS 应用!做得好!

目标菜单有一个显示连接到你的 Mac 的物理设备的部分,以及一个构建部分。你可能想知道它们有什么用。让我们在下一节中看看。

理解构建部分

在上一节中,你学习了如何在目标菜单中选择模拟设备来运行你的应用。除了模拟设备的列表外,此菜单还有一个显示连接到你的 Mac 的物理设备的部分,以及一个构建部分。

这些功能允许你在实际的 Mac 或 iOS 设备上运行应用,并为提交到 App Store 做准备。

点击工具栏中的目标菜单以查看菜单顶部的物理设备和构建部分:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_18.png

图 1.18:Xcode 目标菜单显示设备和构建部分

如果你有一台 Apple Silicon Mac,物理设备部分将显示文本说明 我的 Mac(专为 iPad 设计),因为 Apple Silicon Mac 可以运行 iOS 应用。否则,将显示 无设备。如果你插入了一个 iOS 设备,它将出现在此部分,并且你可以运行你为测试而开发的 app。在真实设备上运行你的 app 是推荐的,因为模拟器无法准确反映真实 iOS 设备的性能特征,并且没有真实设备所具有的硬件功能。

构建部分有两个菜单项,任何 iOS 设备(arm64) 和 任何 iOS 模拟器设备 (arm64, x86_64)。这些用于在提交到 App Store 之前存档你的 app。你将在 第二十七章测试并将你的 app 提交到 App Store 中学习如何这样做。

现在我们来看看如何在真实的 iOS 设备上构建和运行你的 app。尽管这本书中的大多数说明不需要你拥有 iOS 设备,但如果你没有,你可以跳过下一节,直接进入 第二章简单值和类型

在 iOS 设备上运行你的 app

虽然你将能够使用模拟器完成这本书中的大多数练习,但建议在真实设备上构建和测试你的 app,因为模拟器无法模拟某些硬件组件和软件 API。

要全面了解模拟器和实际设备之间的所有差异,请参阅此链接:https://help.apple.com/simulator/mac/current/#/devb0244142d。

除了你的设备外,你还需要一个 Apple 账户(用于自动创建免费的 Apple 开发者账户)或付费的 Apple 开发者账户,才能在你的设备上构建和运行你的 app。你可以使用你从 App Store 下载 Xcode 时使用的同一个 Apple 账户。要在 iOS 设备上运行你的 app,请按照以下步骤操作:

  1. 使用随你的 iOS 设备一起提供的电缆将你的设备连接到你的 Mac,并确保 iOS 设备已解锁。

  2. 你的 Mac 将显示一个 允许配件连接 提示。点击 允许

  3. 你的 iOS 设备将显示一个 信任此计算机 提示。轻触 信任 并在提示时输入你的设备密码。你的 iOS 设备现在已连接到你的 Mac,并将在 Xcode 的目标菜单中显示。

  4. 在 Xcode 菜单栏中选择 窗口 | 设备和模拟器。你将看到一个显示消息的窗口,说明 开发者模式已禁用

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_19.png

图 1.19:Xcode 设备和模拟器窗口显示开发者模式已禁用

Apple 在 2022 年的全球开发者大会(WWDC 2022)期间引入了开发者模式,这是在运行 iOS 16 或更高版本的设备上安装、运行和调试你的 app 所必需的。

要观看关于开发者模式的 WWDC 2022 视频,请点击此链接:developer.apple.com/videos/play/wwdc2022/110344/

  1. 要在您的 iOS 设备上启用开发者模式,请转到 设置 | 隐私与安全,向下滚动到 开发者模式 项,并点击它:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_20.png

图 1.20:隐私与安全屏幕显示开发者模式

  1. 打开 开发者模式 开关:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_21.png

图 1.21:开发者模式开关

  1. 将会弹出一个警告,提醒您开发者模式会降低您的 iOS 设备的安全性。点击警告的 重启 按钮。

  2. 在您的 iOS 设备重新启动并解锁后,通过点击 启用 并输入您的 iOS 设备密码来确认您想要启用 开发者模式

  3. 设备和模拟器窗口将显示 准备 iPhone 信息。等待几分钟,然后确认设备和模拟器窗口不再显示 开发者模式已禁用 文本:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_22.png

图 1.22:Xcode 设备和模拟器窗口显示准备 iPhone 信息

您的 iOS 设备现在已准备好安装和运行来自 Xcode 的应用程序。

  1. 在 Xcode 中,从目标菜单中选择您的 iOS 设备。

  2. 通过点击运行按钮(或使用 Command + R)来运行项目。您将在 Xcode 的 签名与能力 面板中遇到以下错误:“JRNL”的签名需要一个开发团队

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_23.png

图 1.23:Xcode 签名与能力面板

这是因为要在 iOS 设备上运行应用程序需要数字证书,您需要将免费或付费的 Apple 开发者账户添加到 Xcode,以便生成数字证书。

使用 Apple 账户创建免费的开发者账户将允许您在 iOS 设备上测试您的应用程序,但它仅有效期为 7 天。此外,您还需要付费的 Apple 开发者账户才能在 App Store 上分发应用程序。您将在第二十七章 测试和提交您的应用程序到 App Store 中了解更多信息。

证书确保只有您授权的应用程序才能在您的设备上运行。这有助于防止恶意软件。您也可以通过此链接了解更多信息:https://help.apple.com/xcode/mac/current/#/dev60b6fbbc7。

  1. 点击 添加账户… 按钮:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_24.png

图 1.24:Xcode 签名与能力面板,已选择 添加账户… 按钮

  1. Xcode 设置 窗口出现,并选中了 账户 选项卡。输入您的 Apple 账户并点击 下一步

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_25.png

图 1.25:创建 Apple 账户对话框

注意,如果您愿意,可以使用 创建 Apple ID 按钮创建不同的 Apple 账户。

您也可以通过在 Xcode 菜单中选择 设置 来访问 Xcode 设置。

  1. 当提示时输入您的密码。几分钟后,账户 选项卡将显示您的账户设置:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_26.png

图 1.26:Xcode 预设中的账户选项卡

  1. 完成后,通过点击左上角的红色关闭按钮关闭 设置 窗口。

  2. 在 Xcode 的编辑区域中,点击签名与功能。确保自动管理签名被勾选,并且从团队下拉菜单中选择个人团队

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_27.png

图 1.27:Xcode 签名与功能面板,已设置账户

  1. 如果您在此屏幕上仍然看到错误,请尝试通过在其中输入一些随机字符来更改您的包标识符,例如,com.myname6712.JRNL

  2. 构建并运行您的应用程序。如果您被提示输入密码,请输入您的 Mac 登录密码并点击始终允许

  3. 您的应用程序将安装在您的 iOS 设备上。然而,它将无法启动,您将看到以下信息:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_28.png

图 1.28:无法启动“JRNL”对话框

  1. 这意味着您需要信任已安装到您设备上的证书。您将在下一节中学习如何做到这一点。

在您的 iOS 设备上信任开发者应用程序证书

开发者应用程序证书是一个特殊文件,它将与应用程序一起安装到您的 iOS 设备上。在您的应用程序可以运行之前,您需要信任它。按照以下步骤操作:

  1. 在您的 iOS 设备上,点击设置 | 通用 | VPN 与设备管理

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_29.png

图 1.29:设置中的 VPN 与设备管理设置

  1. 点击您的 Apple 账户:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_30.png

图 1.30:设备管理设置中的您的 Apple 账户

  1. 点击信任

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_31.png

图 1.31:信任按钮

  1. 点击允许

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_32.png

图 1.32:允许对话框

您应该看到以下文本,这表明应用程序现在已被信任:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_01_33.png

图 1.33:设备管理部分,带有已信任证书

  1. 在 Xcode 中点击运行按钮以构建和再次运行。您将看到您的应用程序在 iOS 设备上启动并运行。

恭喜!您已成功在真实 iOS 设备上运行了您的应用程序!

摘要

在本章中,您学习了如何在 Mac 上下载和安装 Xcode。然后,您熟悉了 Xcode 用户界面的不同部分。之后,您创建了您的第一个 iOS 应用程序,选择了一个模拟 iOS 设备,并在模拟器中构建和运行了应用程序。最后,您学习了如何通过 USB 将 iOS 设备连接到 Xcode,以便您可以在其上运行应用程序。

在下一章中,我们将开始使用 Swift Playgrounds 探索 Swift 语言,并学习简单的值和类型如何在 Swift 中实现。

加入我们的 Discord!

与其他用户、专家和作者本人一起阅读这本书。提出问题,为其他读者提供解决方案,通过 Ask Me Anything 会议与作者聊天,等等。扫描二维码或访问链接加入社区。

packt.link/ios-Swift

https://packt.link/ios-Swift

第二章:简单值和类型

现在你已经在前一章中对 Xcode 进行了简要的浏览,让我们来看看你将用来编写应用的 Swift 编程语言。

首先,你将探索 Swift 游乐场,这是一个交互式环境,你可以在此处输入 Swift 代码,并立即显示结果。然后,你将学习 Swift 如何表示和存储各种类型的数据。之后,你将了解一些酷炫的 Swift 功能,例如 类型推断类型安全,这些功能可以帮助你更简洁地编写代码并避免常见错误。最后,你将学习如何对数据进行常见操作以及如何将消息打印到调试区域以帮助你解决问题。

到本章结束时,你应该能够编写简单的程序来存储和处理字母和数字。

以下主题将涵盖:

技术要求

要完成本章的练习,你需要以下内容:

  • 运行 macOS 14 Sonoma 或 macOS 15 Sequoia 的苹果 Mac 电脑

  • 已安装 Xcode 16(有关安装 Xcode 的说明,请参阅 第一章探索 Xcode

本章节的 Xcode 游乐场位于本书代码包的 Chapter02 文件夹中,可在此处下载:

github.com/PacktPublishing/iOS-18-Programming-for-Beginners-Ninth-Edition

观看以下视频以查看代码的实际效果:

youtu.be/lSBD_Wacpdc

在下一节中,你将创建一个新的游乐场,你可以在其中输入本章中展示的代码。

介绍 Swift 游乐场

游乐场是交互式编码环境。你在左侧面板中输入代码,结果会立即在右侧面板中显示。这是一种很好的实验代码和探索 iOS SDK 的方法。

SDK 是软件开发工具包的缩写。要了解更多关于 iOS SDK 的信息,请访问 developer.apple.com/ios/

让我们从创建一个新的游乐场并检查其用户界面开始。按照以下步骤操作:

  1. 要创建游乐场,启动 Xcode 并从 Xcode 菜单栏中选择 文件 | 新建 | 游乐场…

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_02_01.png

图 2.1:选择 File | New | Playground… 的 Xcode 菜单栏

  1. 选择一个模板以创建新的游乐场:屏幕出现。iOS 应已选中。选择 空白 并点击 下一步

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_02_02.png

图 2.2:为新游乐场选择模板:屏幕

  1. 将你的游乐场命名为 SimpleValues 并保存到任何你喜欢的位置。完成后点击 创建

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_02_03.png

图 2.3:保存对话框

  1. 你会在屏幕上看到游乐场:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_02_04.png

图 2.4:Xcode 游乐场用户界面

如你所见,它比 Xcode 项目简单得多。让我们更详细地看看界面:

  • 导航按钮(1):这会显示或隐藏导航区域。

  • 活动视图(2):这显示了当前的操作或状态。

  • 库按钮(3):这会显示代码片段和其他资源。

  • 检查器按钮(4):这会显示或隐藏检查器区域。

  • 导航区域(5):这提供了快速访问项目各个部分的途径。默认情况下显示项目导航器。

  • 编辑器区域(6):你在这里编写代码。

  • 结果区域(7):这为你编写的代码提供即时反馈。

  • 运行按钮(8):这会从选定的行执行代码。

  • 边框(9):这个边框分隔了编辑器和结果区域。如果你发现结果区域显示的结果被截断,可以将边框向左拖动以增加其大小。

  • 运行/停止按钮(10):这会执行或停止游乐场中所有代码的执行。

  • 调试区域(11):这会显示 print() 命令的结果。

  • 调试按钮(12):这会显示或隐藏调试区域。

你可能会发现游乐场中的文本太小,难以阅读。让我们看看如何在下一节中将其放大。

自定义字体和颜色

Xcode 提供了广泛的定制选项。你可以在 设置… 菜单中访问它们。如果你发现文本太小,难以看清,请按照以下步骤操作:

  1. 从 Xcode 菜单中选择 设置… 以显示设置窗口。

  2. 在设置窗口中,点击 主题 并选择 演示(浅色) 以使文本更大,更容易阅读:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_02_05.png

图 2.5:选择主题面板的 Xcode 设置窗口

  1. 关闭设置窗口返回到游乐场。注意,游乐场中的文本比之前更大。你也可以尝试其他主题。

现在你已经根据自己的喜好自定义了字体和颜色,让我们看看如何在下一节中运行游乐场代码。

运行游乐场代码

你的游乐场中已经包含了一条指令。要执行指令,请按照以下步骤操作:

  1. 点击指令左侧的运行按钮。几秒钟后,你将在结果区域看到 "``Hello, playground"

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_02_06.png

图 2.6:游乐场结果显示区域显示“Hello, playground”

你也可以使用左下角的运行/停止按钮,或者使用键盘快捷键 Command + Shift + Return 来运行游乐场中的所有代码。

  1. 为了准备游乐场在本章剩余部分的使用,请从游乐场中删除 var greeting = "Hello, playground" 指令。随着你的操作,将本章中显示的代码输入到游乐场中,并点击最后一行左侧的运行按钮来运行它。

在下一节中,让我们深入了解 Swift 中使用的简单数据类型。

探索数据类型

所有编程语言都可以存储数字、单词和逻辑状态,Swift 也不例外。即使你是一位经验丰富的程序员,你也可能会发现 Swift 对这些值的表示与其他你可能熟悉的语言不同。

更多有关数据类型的信息,请访问 docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics.

在下一节中,我们将逐步介绍 Swift 中的 整数浮点数字符串布尔值

表示整数

假设你想要存储以下内容:

  • 城市中的餐馆数量

  • 飞机上的乘客

  • 酒店的房间

你会使用整数,它们是没有分数部分的数字(包括负数)。

Swift 中的整数由 Int 类型表示。

表示浮点数

假设你想要存储以下内容:

  • 圆周率(3.14159…)

  • 绝对零度(-273.15°C)

你会使用带有分数部分的浮点数。

Swift 中浮点数的默认类型是 Double,它使用 64 位,包括负数。你也可以使用 Float,它使用 32 位,但 Double 是默认表示。

表示字符串

假设你想要存储以下内容:

  • 餐馆的名称,例如“孟买宫殿”

  • 职位描述,例如“会计”或“程序员”

  • 一种水果,例如“香蕉”

你会使用 Swift 的 String 类型,它表示字符序列,并且完全符合 Unicode 标准。这使得表示不同的字体和语言变得容易。

想了解更多关于 Unicode 的信息,请访问此链接:home.unicode.org/basic-info/faq/.

表示布尔值

假设你想要存储简单的是/否问题的答案,例如以下内容:

  • 是否在下雨?

  • 餐馆是否有空位?

对于此,你使用布尔值。Swift 提供了一个 Bool 类型,可以被分配 truefalse

现在你已经了解了 Swift 如何表示这些常见的数据类型,让我们在前面创建的游乐场中尝试它们,下一节将进行操作。

在游乐场中使用常见的数据类型

你在游乐场中输入的任何内容都将被执行,结果将显示在结果区域。让我们看看当你将数字、字符串和布尔值输入到你的游乐场并执行时会发生什么。按照以下步骤操作:

  1. 将以下代码输入到你的游乐场的编辑器区域:

    // SimpleValues
    42
    -23
    3.14159
    0.1
    -273.15
    "hello, world"
    "albatross"
    true
    false 
    

注意,任何以//开头的行都是注释。注释是为自己创建笔记或提醒的好方法,并且会被 Xcode 忽略。

  1. 点击最后一行左侧的运行按钮来运行你的代码。

  2. 等待几秒钟。Xcode 将评估你的输入并在结果区域显示结果,如下所示:

    42
    -23
    3.14159
    0.1
    -273.15
    "hello, world"
    "albatross"
    true
    false 
    

注意,注释不会出现在结果区域。

太棒了!你已经创建并运行了你的第一个沙盒。让我们看看如何在下一节中存储不同的数据类型。

探索常量和变量

现在你已经了解了 Swift 支持的基本数据类型,让我们看看如何存储它们,以便你可以在以后对它们进行操作。

你可以使用常量变量来存储值。两者都是具有名称的容器,但常量的值只能设置一次,一旦设置就不能更改,而变量的值可以在任何时候更改。

在使用之前,你必须声明常量和变量。常量使用let关键字声明,而变量使用var关键字声明。

让我们通过在我们的沙盒中实现它们来探索常量和变量是如何工作的。按照以下步骤操作:

  1. 将以下代码添加到你的沙盒中,以声明三个常量:

    let theAnswerToTheUltimateQuestion = 42
    let pi = 3.14159
    let myName = "Ahmad Sahar" 
    
  2. 点击最后一行左侧的运行按钮来运行它。在每种情况下,都会创建一个容器并命名,并将分配的值存储在其中。

你可能已经注意到这里显示的常量和变量的名称以小写字母开头,并且如果名称中有多个单词,则每个后续单词的首字母都大写。这被称为驼峰式命名法。强烈建议这样做,因为大多数经验丰富的 Swift 程序员都遵循这个约定。

注意,用双引号括起来的字符序列"Ahmad Sahar"用于为myName分配值。这些被称为字符串字面量

  1. 在常量声明之后添加以下代码来声明三个变量并运行它:

    var currentTemperatureInCelsius = 27
    var myAge = 50
    var myLocation = "home" 
    

与常量一样,在每种情况下都会创建一个容器并命名,并将分配的值存储在其中。

存储的值会在结果区域显示。

  1. 常量的值一旦设置就不能更改。为了测试这一点,在变量声明之后添加以下代码:

    let isRaining = true
    isRaining = false 
    

当你输入第二行代码时,会出现一个带有建议的弹出菜单:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_02_07.png

图 2.7:自动完成弹出菜单

使用上箭头键和下箭头键选择isRaining常量,然后按Tab键选择它。这个功能被称为自动完成,有助于在输入代码时防止输入错误。

  1. 当你完成输入后,等待几秒钟。在第二行,你会看到一个错误通知(一个中间有白色点的红色圆圈)出现:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_02_08.png

图 2.8:错误通知

这意味着你的程序中存在错误,Xcode 认为它可以修复。错误出现是因为你试图在设置初始值后为常量分配新值。

  1. 点击红色圆圈以展开错误消息。你会看到一个带有修复按钮的框:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_02_09.png

图 2.9:扩展的错误通知

Xcode 告诉你问题是什么(无法赋值:'isRaining’是一个’let’常量)并建议一个修正(将’let’改为’var’以使其可变)。"可变"的意思是值可以在最初设置后更改。

  1. 点击修复按钮。你会看到isRaining常量声明已被更改为变量声明:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_02_10.png

图 2.10:应用了修复的代码

由于可以在创建变量后为其分配新值,错误已解决。但是请注意,建议的修复可能不是最佳解决方案。随着你在 iOS 开发方面经验的增加,你将能够确定最佳的行动方案。

如果你查看你输入的代码,你可能想知道 Xcode 是如何知道变量或常量中存储的数据类型的。你将在下一节中了解这一点。

理解类型推断和类型安全

在上一节中,你声明了常量和变量并给它们赋值。Swift 会根据提供的值自动确定常量或变量的类型,这被称为类型推断。你可以通过按住选项键并点击其名称来查看常量或变量的类型。为了看到这一点是如何发生的,请按照以下步骤操作:

  1. 将以下代码添加到你的游乐场中,以声明一个字符串并运行它:

    let cuisine = "American" 
    
  2. 按住选项键并点击cuisine以显示常量类型。你应该看到以下内容:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_02_11.png

图 2.11:显示的类型声明

如你所见,cuisine的类型是String

如果你想为变量或常量设置一个特定的类型?你将在下一节中看到如何做到这一点。

使用类型注解来指定类型

你已经看到 Xcode 会尝试根据提供的值自动确定变量或常量的数据类型。然而,有时你可能希望指定一个类型而不是让 Xcode 为你做这件事。为此,在常量或变量名称后输入一个冒号(:),然后跟随着期望的类型。这被称为类型注解

将以下代码添加到你的游乐场中,以声明一个类型为Double的变量restaurantRating,然后点击运行按钮来运行它:

var restaurantRating: Double = 3 

在这里,你指定了restaurantRating具有特定的类型,Double。即使你为restaurantRating分配了一个整数,它也会被存储为浮点数。

在下一节中,你将了解 Xcode 如何通过强制类型安全来帮助你减少程序中的错误数量。

使用类型安全来检查值

Swift 是一种类型安全的语言。它会检查你是否将正确类型的值分配给变量,并将不匹配的类型标记为错误。让我们通过以下步骤来了解它是如何工作的:

  1. 将以下语句添加到你的游乐场中,以将字符串分配给 restaurantRating 并运行它:

    restaurantRating = "Good" 
    
  2. 你会看到一个错误通知(一个带有 x 的红色圆圈)。x 表示 Xcode 无法为此提供修复方案。点击红色圆圈。

  3. 由于你试图将一个字符串分配给类型为 Double 的变量,因此会显示以下错误消息:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_02_12.png

图 2.12:无修复方案的扩展错误通知

  1. 在它前面输入 // 来注释掉该行,如下所示:

    // restaurantRating = "Good" 
    

红色圆圈消失了,因为你的程序中不再有错误。

选择代码行并输入 Command + / 来注释掉它们。

现在你已经知道了如何将数据存储在常量和变量中,让我们看看如何在下一节中对这些数据进行操作。

探索运算符

你可以在 Swift 中执行算术、比较和逻辑运算。算术运算符用于常见的数学运算。比较逻辑运算符检查表达式的值并返回 truefalse

更多关于运算符的信息,请访问 docs.swift.org/swift-book/documentation/the-swift-programming-language/basicoperators

让我们更详细地查看每种运算符类型。你将在下一节中从算术运算符(加法、减法、乘法和除法)开始。

使用算术运算符

你可以使用这里显示的标准算术运算符对整数和浮点数执行数学运算。

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_02_13.png

图 2.13:算术运算符

让我们看看这些运算符是如何使用的。按照以下步骤操作:

  1. 将以下代码添加到你的游乐场中,以添加算术运算:

    let sum = 23 + 20
    let result = 32 - sum
    let total = result * 5
    let divide = total / 10 
    
  2. 运行代码。结果区域显示的结果分别是 43-11-55-5。请注意,55 除以 10 返回 5 而不是 5.5,因为这两个数都是整数。

  3. 运算符只能与相同类型的操作数一起工作。输入以下代码并运行,看看如果操作数是不同类型会发生什么:

    let a = 12
    let b = 12.0
    let c = a + b 
    

你会得到一个错误消息(二进制运算符 ‘+’ 无法应用于类型 ‘Int’ 和 ‘Double’ 的操作数)。这是因为 ab 是不同类型的。请注意,Xcode 无法自动修复此问题,因此不会显示任何修复建议。

  1. 要修复错误,请按以下方式修改程序:

    let c = Double(a) + b 
    

Double(a) 获取存储在 a 中的值,并从中创建一个浮点数。现在两个操作数都是同一类型,现在你可以将 b 中的值加到它上面。存储在 c 中的值是 24.0,而 24 将在结果区域显示。

现在您已经了解了如何使用算术运算符,您将学习下一节中的复合赋值运算符(+=、-=、*= 和 /=)。

使用复合赋值运算符

您可以使用复合赋值运算符(如下所示)对一个值执行操作并将结果赋给一个变量:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_02_14.png

图 2.14:复合赋值运算符

让我们看看这些运算符是如何使用的。将以下代码添加到您的游乐场并运行它:

var d = 1
d += 2
d -= 1 

d += 2 表达式是 d = d + 2 的简写,因此 d 中的值现在是 1 + 2,并将 3 赋值给 d。同样,d -= 1d = d - 1 的简写,因此 d 中的值现在是 3 - 1,并将 2 赋值给 d

现在您已经熟悉了复合赋值运算符,让我们看看下一节中的比较运算符(==、/、>、<、>= 和 <=)。

使用比较运算符

您可以使用比较运算符将一个值与另一个值进行比较,结果将是 truefalse。您可以使用以下比较运算符:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_02_15.png

图 2.15:比较运算符

让我们看看这些运算符是如何使用的。将以下代码添加到您的游乐场并运行它:

1 == 1
2 != 1
2 > 1   
1 < 2   
1 >= 1
2 <= 1 

让我们看看这是如何工作的:

  • 1 == 1 返回 true,因为 1 等于 1。

  • 2 != 1 返回 true,因为 2 不等于 1。

  • 2 > 1 返回 true,因为 2 大于 1。

  • 1 < 2 返回 true,因为 1 小于 2。

  • 1 >= 1 返回 true,因为 1 大于或等于 1。

  • 2 <= 1 返回 false,因为 2 不小于或等于 1。

返回的布尔值将在结果区域显示。

如果您想检查多个条件会发生什么?这就是逻辑运算符(ANDORNOT)发挥作用的地方。您将在下一节中了解它们。

使用逻辑运算符

逻辑运算符在处理两个或多个条件时非常有用。例如,如果您在便利店,如果您有现金或信用卡,您就可以为商品付款。在这种情况下,OR 是逻辑运算符。

您可以使用以下逻辑运算符:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_02_16.png

图 2.16:逻辑运算符

要查看这些运算符的使用方法,将以下代码添加到您的游乐场并运行它:

(1 == 1) && (2 == 2)
(1 == 1) && (2 != 2)
(1 == 1) || (2 == 2)
(1 == 1) || (2 != 2)
(1 != 1) || (2 != 2)
!(1 == 1) 

让我们看看这是如何工作的:

  • (1 == 1) && (2 == 2) 返回 true,因为两个操作数都是 true,所以 true AND true 返回 true

  • (1 == 1) && (2 != 2) 返回 false,因为一个操作数是 false,所以 true AND false 返回 false

  • (1 == 1) || (2 == 2) 返回 true,因为两个操作数都是 true,所以 true OR true 返回 true

  • (1 == 1) || (2 != 2) 返回 true,因为一个操作数是 true,所以 true OR false 返回 true

  • (1 != 1) || (2 != 2) 返回 false,因为两个操作数都是 false,所以 false OR false 返回 false

  • !(1 == 1) 返回 false,因为 1==1true,所以 NOT true 返回 false

返回的布尔值将在结果区域显示。

到目前为止,你只处理过数字。在下一节中,你将看到如何使用 Swift 的 String 类型对单词和句子进行操作,这些单词和句子被存储为字符串。

执行字符串操作

如你之前所见,字符串是一系列字符。它们由 String 类型表示,并且完全符合 Unicode 标准。

更多有关字符串的信息,请访问 docs.swift.org/swift-book/documentation/the-swift-programming-language/stringsandcharacters

让我们学习一些常见的字符串操作。按照以下步骤操作:

  1. 你可以使用 + 运算符将两个字符串连接起来。将以下代码添加到你的游乐场中并运行它:

    let greeting = "Good" + " Morning" 
    

字符串字面量 "Good""Morning" 的值被连接起来,并在结果区域显示 "Good Morning"

  1. 你可以通过将其他类型的常量或变量也转换为字符串来组合字符串。要将常量 rating 转换为字符串,输入以下代码并运行它:

    let rating = 3.5
    var ratingResult = "The restaurant rating is " + String(rating) 
    

rating 常量包含 3.5,这是一个 Double 类型的值。将 rating 放在 String() 的括号中,会获取 rating 中存储的值并基于它创建一个新的字符串 "3.5",然后与 ratingResult 变量中的字符串组合,返回字符串 "The restaurant rating is 3.5"

  1. 有一种更简单的方法来组合字符串,称为 字符串插值。字符串插值是通过在字符串中用 "\("")" 包围一个常量或变量的名称来完成的。输入以下代码并运行它:

    ratingResult = "The restaurant rating is \(rating)" 
    

如前例所示,rating 中的值被用来创建一个新的字符串 "3.5",返回字符串 "The restaurant rating is 3.5"

到目前为止,你可以在结果区域看到你的指令结果。然而,当你使用 Xcode 编写应用程序时,你将无法访问你在游乐场中看到的结果区域。为了在程序运行时显示变量和常量的内容,你将在下一节中学习如何将它们打印到调试区域。

使用 print() 语句

如你在 第一章探索 Xcode 中所见,Xcode 项目没有像游乐场那样的结果区域,但项目和游乐场都有调试区域。使用 print() 语句会将括号内的任何内容打印到调试区域。

print() 语句是一个函数。你将在 第六章函数和闭包 中了解更多关于函数的内容。

将以下代码添加到你的游乐场中,然后点击 运行 按钮来运行它:

print(ratingResult) 

你将看到 ratingResult 的值出现在调试区域:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_02_17.png

图 2.17:调试区域显示 print() 语句的结果

当你刚开始时,可以随意使用尽可能多的 print() 语句。这是一个真正理解程序中发生情况的好方法。

概述

在本章中,你学习了如何创建和使用游乐场文件,这允许你探索和实验 Swift。

你看到了 Swift 如何表示不同类型的数据,以及如何使用常量和变量。这使你能够在程序中存储数字、布尔值和字符串。

你还学习了类型推断、类型注解和类型安全,这些可以帮助你编写简洁且错误更少的代码。

你了解了如何对数字和字符串进行操作,这让你能够执行简单的数据处理任务。

你学习了如何修复错误,以及如何将输出打印到调试区域,这在尝试查找和修复你编写的程序中的错误时非常有用。

在下一章中,你将学习条件语句可选参数。条件语句用于在程序中做出逻辑选择,而可选参数用于处理变量可能或可能没有值的情况。

加入我们的 Discord!

与其他用户、专家和作者本人一起阅读这本书。提出问题,为其他读者提供解决方案,通过“问我任何问题”的环节与作者聊天,等等。扫描二维码或访问链接加入社区。

packt.link/ios-Swift

https://packt.link/ios-Swift

第三章:条件语句和可选

在上一章中,你学习了数据类型、常量、变量和操作。到这一点,你可以编写简单的程序来处理字母和数字。然而,程序并不总是按顺序执行。很多时候,你需要根据条件执行不同的指令。Swift 允许你通过使用 条件语句 来做到这一点,你将学习如何使用它们。

你可能还注意到,在上一章中,每个变量或常量都被立即赋予了一个值。如果你需要一个可能最初没有值的变量,你将需要一个方法来创建一个可能或可能没有值的变量。Swift 允许你通过使用 可选 来做到这一点,你也将在这章中了解它们。

到本章结束时,你应该能够编写根据不同条件执行不同操作的程序,并处理可能或可能没有值的变量。

以下内容将涵盖:

  • 介绍条件语句

  • 介绍可选和可选绑定

请花些时间了解可选。对于新手程序员来说,它们可能有些令人畏惧,但正如你将看到的,它们是 iOS 开发的重要组成部分。

技术要求

本章的 Xcode 演示场位于本书代码包的 Chapter03 文件夹中,可以在此处下载:

github.com/PacktPublishing/iOS-18-Programming-for-Beginners-Ninth-Edition

查看以下视频以查看代码的实际运行情况:

youtu.be/f90pTabsOgc

创建一个新的演示场,并将其命名为 ConditionalsAndOptionals。你可以一边阅读一边输入并运行本章中的所有代码。你将从学习条件语句开始。

介绍条件语句

有时,你将想要根据特定的条件执行不同的代码块,例如在以下场景中:

  • 在酒店中选择不同的房间类型。大房间的价格会更高。

  • 在在线商店之间切换不同的支付方式。不同的支付方式会有不同的程序。

  • 在快餐店决定要订购什么。每种食品的准备程序都不同。

要做到这一点,你会使用条件语句。在 Swift 中,这是通过使用 if 语句(用于单个条件)和 switch 语句(用于多个条件)来实现的。

更多有关条件语句的信息,请访问 docs.swift.org/swift-book/documentation/the-swift-programming-language/controlflow

让我们看看在下一节中如何使用 if 语句根据条件值执行不同的任务。

使用 if 语句

if语句在条件为true时执行一段代码,如果条件为false,则可选地执行另一段代码。它看起来像这样:

if condition {
  code1
} else {
  code2
} 

让我们实现一个if语句来观察其效果。想象一下,你正在为一家餐厅编写应用程序。该应用程序将允许你检查餐厅是否营业,搜索餐厅,并检查顾客是否超过饮酒年龄限制。按照以下步骤操作:

  1. 要检查餐厅是否营业,将以下代码添加到你的 playground 中。运行它以创建一个常量,并在常量的值为true时执行一个语句:

    let isRestaurantOpen = true
    if isRestaurantOpen {
      print("Restaurant is open.")
    } 
    

首先,你创建了一个常量isRestaurantOpen,并将其赋值为true。接下来,你有一个if语句,它会检查isRestaurantOpen中存储的值。由于值是trueprint()语句被执行,并在 Debug 区域打印出Restaurant is open

  1. 尝试将isRestaurantOpen的值改为false并再次运行你的代码。由于当前条件是false,Debug 区域将不会打印任何内容。

  2. 你也可以在值为false时执行语句。假设顾客搜索的餐厅不在应用程序的数据库中,因此应用程序应显示一条消息表示餐厅未找到。输入以下代码以创建一个常量,并在常量的值为false时执行一个语句:

    let isRestaurantFound = false
    if isRestaurantFound == false {
      print("Restaurant was not found")
    } 
    

常量isRestaurantFound被设置为false。接下来,检查if语句。isRestaurantFound == false条件返回true,并在 Debug 区域打印出Restaurant was not found

你也可以使用!isRestaurantFound代替isRestaurantFound == false来检查条件。

  1. 尝试将isRestaurantFound的值改为true。由于当前条件是false,Debug 区域将不会打印任何内容。

  2. 要在条件为true时执行一组语句,在条件为false时执行另一组语句,请使用else关键字。输入以下代码,该代码检查酒吧中的顾客是否超过饮酒年龄限制:

    let drinkingAgeLimit = 21
    let customerAge = 23
    if customerAge < drinkingAgeLimit {
      print("Under age limit")
    } else {
      print("Over age limit")
    } 
    

在这里,drinkingAgeLimit被赋值为21customerAge被赋值为23。在if语句中,检查customerAge < drinkingAgeLimit。由于 23 < 21 返回false,所以执行else语句,并在 Debug 区域打印出Over age limit。如果你将customerAge的值改为19customerAge < drinkingAgeLimit将返回true,因此将在 Debug 区域打印出Under age limit

到目前为止,你只处理了单个条件。如果有多个条件怎么办?这就是switch语句的用武之地,你将在下一节中学习它们。

使用switch语句

要理解switch语句,我们先从实现一个带有多个条件的if语句开始。想象一下你正在编写交通灯的代码。交通灯有三种可能的颜色——红色、黄色或绿色——并且你希望根据灯的颜色执行不同的操作。为此,你可以嵌套多个if语句。按照以下步骤操作:

  1. 将以下代码添加到你的游乐场中,以使用多个if语句实现交通灯,并运行它:

    var trafficLightColor = "Yellow"
    if trafficLightColor == "Red" {
      print("Stop")
    } else if trafficLightColor == "Yellow" {
      print("Caution")
    } else if trafficLightColor == "Green" {
      print("Go")
    } else {
      print("Invalid color")
    } 
    

第一个if条件trafficLightColor == "Red"返回false,因此执行else语句。第二个if条件trafficLightColor == "Yellow"返回true,所以在调试区域打印出Caution,并且不再评估更多的if条件。尝试更改trafficLightColor的值以查看不同的结果。

这里使用的代码是有效的,但读起来有点困难。在这种情况下,使用switch语句会更加简洁且易于理解。switch语句看起来是这样的:

switch value {
case firstValue:
  code1
case secondValue:
  code2
default:
  code3
} 

值会被检查并与某个case匹配,然后执行该case的代码。如果没有任何一个case匹配,则执行default中的代码。

  1. 这是如何将前面显示的if语句写成switch语句的方法。输入以下代码并运行:

    trafficLightColor = "Yellow"
    switch trafficLightColor {
    case "Red":
      print("Stop")
    case "Yellow":
      print("Caution")
    case "Green":
      print("Go")
    default:
      print("Invalid color")
    } 
    

与之前的版本相比,这里的代码更容易阅读和理解。trafficLightColor中的值是"Yellow",所以case "Yellow":被匹配,并在调试区域打印出Caution。尝试更改trafficLightColor的值以查看不同的结果。

关于switch语句有两点需要注意:

  • Swift 中的switch语句默认不会从每个case的底部跌落到下一个case。在前面显示的示例中,一旦case "Yellow":被匹配,case "Red"case "Green"default:将不会执行。

  • switch语句必须覆盖所有可能的case。在前面显示的示例中,任何除了"Red""Yellow""Green"之外的trafficLightColor值都将匹配到default:,并在调试区域打印出Invalid color

这部分关于ifswitch语句的内容到此结束。在下一部分,你将学习可选类型,它允许你创建没有初始值的变量,以及可选绑定,它允许在可选类型有值时执行指令。

介绍可选类型和可选绑定

到目前为止,每次你声明一个变量或常量时,你都会立即给它赋值。但如果你想在声明变量后稍后再赋值呢?在这种情况下,你会使用可选类型。

更多关于可选类型的信息,请访问docs.swift.org/swift-book/documentation/the-swift-programming-language/thebasics

让我们学习如何创建和使用可选类型,并看看它们如何在程序中使用。想象你正在编写一个程序,其中用户需要输入他们配偶的名字。当然,如果用户没有结婚,这个值就不存在。在这种情况下,你可以使用可选来表示配偶的名字。

可选可能有两种可能的状态。它可以包含一个值,或者不包含值。如果可选包含一个值,你可以访问它内部的值。访问可选值的这个过程被称为 解包 可选。让我们通过以下步骤看看这是如何工作的:

  1. 将以下代码添加到你的游乐场中,以创建一个变量并打印其内容:

    var spouseName: String
    print(spouseName) 
    
  2. 由于 Swift 是类型安全的,会出现一个错误,(变量‘spouseName’在使用之前未初始化)

  3. 为了解决这个问题,你可以将空字符串赋值给 spouseName。按照以下方式修改你的代码:

    var spouseName: String **=****""** 
    

这使得错误消失,但空字符串仍然是一个值,而 spouseName 不应该有值。

  1. 由于 spouseName 应该最初没有值,让我们将其设置为可选。要做到这一点,在类型注释后输入一个问号,并删除空字符串赋值:

    var spouseName: String**?** 
    

你会看到一个警告,因为 spouseName 现在是一个可选的字符串变量,而不是一个常规的字符串变量,而 print() 语句期望的是一个常规字符串变量。

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_03_01.png

图 3.1:警告通知

即使有警告,现在先忽略它并运行你的代码。spouseName 的值在结果区域显示为 nil,并且在调试区域打印出 nilnil 是一个特殊的关键字,表示可选变量 spouseName 没有值。

  1. 警告出现是因为 print 语句将 spouseName 视为 Any 类型而不是 String? 类型。点击黄色三角形以显示可能的修复,并选择第一个修复:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_03_02.png

图 3.2:突出显示第一个修复的扩展警告通知

语句将变为 print(spouseName ?? default value)。注意 ?? 操作符的使用。这意味着如果 spouseName 不包含值,将使用你提供的默认值在 print 语句中。

  1. 将默认值占位符替换为 "No value in spouseName",如图所示。警告将会消失。再次运行你的程序,No value in spouseName 将会在调试区域显示:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_03_03.png

图 3.3:显示默认值的调试区域

  1. 让我们给 spouseName 赋予一个值。按照以下方式修改代码:

    var spouseName: String?
    **spouseName****=****"Nia"**
    print(spouseName ?? "No value in spouseName") 
    

当你的程序运行时,Nia 将会在调试区域显示。

  1. 添加一行代码以将 spouseName 与另一个字符串连接,如图所示:

    print(spouseName ?? "No value in spouseName")
    **let****greeting****=****"Hello, "****+****spouseName** 
    

你会得到一个错误,并且调试区域会显示错误信息和错误发生的位置。这是因为你不能使用 + 操作符将常规字符串变量与可选类型连接。你需要首先解包可选类型。

  1. 点击红色圆圈以显示可能的修复方案,你会看到以下内容:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_03_04.png

图 3.4:带有第二个修复方案高亮的扩展错误通知

第二个修复建议使用强制解包来解决这个问题。强制解包无论可选是否包含值都会解包。如果spouseName有值,它将正常工作,但如果spouseNamenil,你的代码将崩溃。

  1. 点击第二个修复方案,你会在代码的最后一行spouseName后面看到一个感叹号,这表示可选被强制解包了:

    let greeting = "Hello, " + spouseName**!** 
    
  2. 运行你的程序,你会在结果区域看到Hello, Nia被分配给greeting,如图所示。这意味着spouseName已经成功被强制解包。

  3. 要查看强制解包包含nil的变量的效果,将spouseName设置为nil

    spouseName = **nil** 
    

你的代码崩溃了,你可以在调试区域中看到导致崩溃的原因:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_03_05.png

图 3.5:崩溃的程序及其在调试区域中的详细信息

由于spouseName现在是nil,程序在尝试强制解包spouseName时崩溃了。

处理这个问题的一个更好的方法是使用可选绑定。在可选绑定中,你尝试将可选中的值分配给一个临时变量(你可以随意命名它)。如果分配成功,将执行一个代码块。

  1. 要查看可选绑定的效果,修改你的代码如下:

    spouseName = **"Nia"**
    print(spouseName ?? "No value in spouseName")
    **if****let** **spouseTempVar** **=****spouseName** **{**
    **let** **greeting** **=****"Hello, "****+****spouseTempVar**
     **print(greeting)**
    **}** 
    

Hello, Nia将出现在调试区域。以下是它是如何工作的。如果spouseName有值,它将被解包并分配给一个临时常量spouseTempVar,然后if语句将返回true。花括号之间的语句将被执行,常量greeting将被分配值Hello, Nia。然后,Hello, Nia将在调试区域打印出来。注意,临时变量spouseTempVar不是一个可选变量。如果spouseName没有值,无法将值分配给spouseTempVarif语句将返回false。在这种情况下,花括号中的语句根本不会执行。

  1. 你也可以以前一个步骤更简单的方式编写代码,如下所示:

    spouseName = "Nia"
    print(spouseName ?? "No value in spouseName")
    if let **spouseName** {
       let greeting = "Hello, " + spouseName
       print(greeting)
    } 
    

在这里,临时常量使用与可选值相同的名称创建,并将用于花括号之间的语句中。

  1. 要查看当可选包含nil时可选绑定的效果,再次将nil分配给spouseName

    spouseName = **nil** 
    

你会注意到调试区域中没有出现任何内容,即使spouseNamenil,你的程序也不再崩溃。

这就结束了关于可选和可选绑定的部分,你现在可以创建和使用可选变量了。太棒了!

摘要

你做得很好!你学习了如何使用ifswitch语句,这意味着你现在能够编写基于不同条件执行不同操作的程序。

你还学习了可选类型和可选绑定。这意味着你现在可以表示可能具有也可能不具有值的变量,并且只有当变量的值存在时才执行指令。

在下一章中,你将学习如何使用一系列值而不是单个值,以及如何使用循环重复程序语句。

加入我们的 Discord 社群!

与其他用户、专家以及作者本人一起阅读这本书。提出问题,为其他读者提供解决方案,通过 Ask Me Anything 会话与作者聊天,等等。扫描二维码或访问链接加入社区。

packt.link/ios-Swift

https://packt.link/ios-Swift

第四章:范围运算符和循环

在上一章中,你学习了条件语句,它允许你根据不同的条件执行不同的操作,以及可选类型,它使你能够创建可能或可能没有值的变量。

在本章中,你将了解范围运算符循环。范围运算符允许你通过指定范围的起始和结束值来表示一系列值。你将了解不同类型的范围运算符。循环允许你重复执行一条指令或一系列指令。你可以重复一个序列固定次数或直到满足某个条件。你将了解用于完成此操作的不同类型的循环。

到本章结束时,你将学会如何使用范围以及创建和使用不同类型的循环(for-inwhilerepeat-while)。

本章将涵盖以下主题:

  • 探索范围运算符

  • 探索循环

技术要求

本章的 Xcode 游乐场位于本书代码包的Chapter04文件夹中,可以从以下链接下载:

github.com/PacktPublishing/iOS-18-Programming-for-Beginners-Ninth-Edition.

查看以下视频,以查看代码的实际运行情况:

youtu.be/swoigirsG_s

如果你希望从头开始,创建一个新的游乐场并将其命名为RangeOperatorsAndLoops

你可以边走边输入并运行本章中的所有代码。让我们从使用范围运算符指定数字范围开始。

探索范围运算符

假设你需要编写一个为百货公司编写程序,该程序可以自动向 18 至 30 岁的顾客发送折扣券。如果需要为每个年龄设置ifswitch语句,将会非常繁琐。在这种情况下使用范围运算符会方便得多。

范围运算符允许你表示一系列值。假设你想要表示一个从firstNumber开始到lastNumber结束的数字序列。你不需要指定每个值;你只需以这种方式指定范围:

firstNumber...lastNumber 

更多关于范围运算符的信息,请访问docs.swift.org/swift-book/documentation/the-swift-programming-language/basicoperators

让我们在游乐场中尝试一下。按照以下步骤操作:

  1. 将以下代码添加到你的游乐场中并运行它:

    let myRange = 10...20 
    

这将为myRange常量分配一个从10开始到20结束的数字序列,包括这两个数字,这被称为闭区间运算符myRange的起始和结束值将在结果区域显示。

  1. 显示在结果区域的结果可能会被截断。点击结果右侧的方块图标。它将在编辑器区域中内联显示:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_04_01.png

图 4.1:显示内联结果的编辑器区域

你现在可以在代码行下面的框中看到完整的结果。如果你愿意,可以拖动框的右边缘使其变大。

记住,你可以拖动结果和编辑器区域之间的边界来增加结果区域的大小。

  1. 如果你不想在范围内包含序列的最后一个数字,将...替换为..<。在下一行输入并运行以下语句:

    let myRange2 = 10..<20 
    

这将在myRange2常量中存储从10开始到19结束的序列,并被称为半开区间范围运算符

还有一种范围运算符类型,即单侧范围运算符,你将在下一章中了解它。

现在你已经知道了如何创建和使用范围,你将在下一节学习循环、不同类型的循环以及如何在程序中使用它们。

探索循环

在编程中,你经常需要重复执行相同的事情。例如,每个月,公司都需要为每位员工生成工资条。如果公司有 10,000 名员工,编写 10,000 条指令来创建工资条将是不高效的。重复一条指令 10,000 次会更好,循环就是为此而用的。

有三种循环类型:for-in循环、while循环和repeat-while循环。for-in循环将重复已知次数,而whilerepeat-while循环将在循环条件为true时重复。

关于循环的更多信息,请访问docs.swift.org/swift-book/documentation/the-swift-programming-language/controlflow

让我们逐一查看每种类型,从for-in循环开始,当你知道循环应该重复多少次时使用。

for-in循环

for-in循环遍历序列中的每个值,并将一组语句(称为循环体)在每次执行时执行。每个值依次分配给一个临时变量,并且可以在循环体内使用这个临时变量。它看起来是这样的:

for item in sequence {
   code
} 

循环重复的次数由序列中的项目数量决定。让我们先创建一个for-in循环来显示myRange中的所有数字。按照以下步骤操作:

  1. 将以下代码添加到你的游乐场中并运行它:

    for number in myRange {
       print(number)
    } 
    

你应该看到序列中的每个数字都在调试区域中显示。请注意,由于myRange包括范围中的最后一个数字,循环内的语句执行了 11 次。

  1. 让我们尝试相同的程序,但这次使用myRange2。按照以下方式修改代码并运行:

    for number in **myRange2** {
       print(number)
    } 
    

循环内的语句执行了 10 次,并且在调试区域中打印的最后一个值是19

  1. 你甚至可以直接在in关键字后面使用范围运算符。输入并运行以下代码:

    for number in 0...5 {
       print(number)
    } 
    

从 0 到 5 的每个数字都在调试区域中显示。

  1. 如果你想序列反向,请使用 reversed() 函数。按照以下方式修改代码并运行:

    for number in **(****0****...****5****).reversed()** {
       print(number)
    } 
    

每个从 5 到 0 的数字都会显示在调试区域中。

干得好!让我们在下一节中检查 while 循环,当循环序列应该在条件为 true 时重复时使用。

当前的循环

while 循环包含一个条件和一组在花括号中的语句,称为循环体。首先检查条件;如果为 true,则执行循环体,并且循环会重复,直到条件为 false。以下是一个 while 循环的示例:

while condition == true {
   code
} 

添加并运行以下代码以创建一个变量,将其增加 5,并且只要变量的值小于 50 就继续这样做:

var x = 0
while x < 50 {
   x += 5
   print("x is \(x)")
} 

让我们逐步分析代码。最初,x 被设置为 0。检查 x < 50 条件并返回 true,因此执行循环体。x 的值增加 5,并在调试区域中打印出 x 是 5。循环重复,再次检查 x < 50。由于 x 现在是 5,并且 5 < 50 仍然返回 true,因此再次执行循环体。这会一直重复,直到 x 的值为 50,此时 x < 50 返回 false,循环停止。

如果 while 循环的条件一开始就是 false,则循环体将永远不会执行。尝试将 x 的值更改为 100 来查看这一点。

在下一节中,你将学习 repeat-while 循环。这些循环首先执行循环体内的语句,然后再检查循环条件。

repeat-while 循环

while 循环一样,repeat-while 循环也包含一个条件和循环体,但循环体在检查条件之前先执行。如果条件为 true,则循环会重复,直到条件返回 false。以下是一个 repeat-while 循环的示例:

repeat {
   code
} while condition == true 

添加并运行以下代码以创建一个变量,将其增加 5,并且只要变量的值小于 50 就继续这样做:

var y = 0
repeat {
   y += 5
   print("y is \(y)")
} while y < 50 

让我们逐步分析代码。最初,y 被设置为 0。执行循环体。y 的值增加 5,因此现在 y 包含 5,并在调试区域中打印出 y 是 5。检查 y < 50 条件,由于它返回 true,因此循环会重复。y 的值增加 5,因此现在 y 包含 10,并在调试区域中打印出 y 是 10。循环会重复,直到 y 包含 50,此时 y < 50 返回 false,循环停止。

即使初始条件为 false,循环体也会至少执行一次。尝试将 y 的值更改为 100 来查看这一点。

你现在已经知道如何创建和使用不同的循环类型。太棒了!

摘要

在本章中,你学习了闭包和半开区间运算符,这些运算符允许你指定一组数字的范围,而不是逐个指定每个单独的数字。

你还学习了三种不同的循环类型:for-in 循环、while 循环和 repeat-while 循环。for-in 循环允许你重复执行一组语句固定次数,而 whilerepeat-while 循环允许在条件为真时重复执行一组语句。做得很好!

在下一章中,你将学习集合类型,这些类型允许你通过索引、键值对以及无结构的 数据集合来存储数据。

加入我们的 Discord 社群!

与其他用户、专家以及作者本人一起阅读这本书。提问、为其他读者提供解决方案、通过“问我任何问题”的环节与作者聊天,以及更多。扫描二维码或访问链接加入社区。

packt.link/ios-Swift

https://packt.link/ios-Swift

第五章:集合类型

到目前为止,你已经学到了很多!你现在可以创建一个存储数据在常量或变量中并对其执行操作的程序,并且你可以使用条件语句和循环来控制流程。但到目前为止,你主要存储的是单个值。

在本章中,你将学习存储值集合的方法。Swift 有三种集合类型:数组,它存储一个有序的值列表;字典,它存储一个无序的键值对列表;以及 集合,它存储一个无序的值列表。

到本章结束时,你将学会如何创建数组、字典和集合,以及如何对它们进行操作。

本章将涵盖以下主题:

  • 探索数组

  • 探索字典

  • 探索集合

技术要求

本章的 Xcode 操场位于本书代码包的 Chapter05 文件夹中,可以在此处下载:

github.com/PacktPublishing/iOS-18-Programming-for-Beginners-Eighth-Edition

查看以下视频以查看代码的实际操作:

youtu.be/W13l9tOMFx8

如果你希望从头开始,创建一个新的操场并将其命名为 CollectionTypes。你可以逐行输入并运行本章中的所有代码。

要了解更多关于数组、字典和集合的信息,请访问 docs.swift.org/swift-book/documentation/the-swift-programming-language/collectiontypes

你将要学习的第一个集合类型是数组,它允许你按有序列表存储信息。

探索数组

假设你想要存储以下内容:

  • 便利店购买物品清单

  • 每月必须做的家务

数组将非常适合这个。数组按有序列表存储值。它看起来是这样的:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_05_01.png

图 5.1:数组表示

值必须是同一类型。你可以通过使用数组索引来访问数组中的任何值,索引从 0 开始。

如果你使用 let 关键字创建一个数组,那么在创建后其内容不能被更改。如果你想创建后更改数组的内容,请使用 var 关键字。

让我们看看如何使用数组。你将在下一节中通过给数组赋值来创建它。

创建数组

在前面的章节中,你通过声明并为其分配一个初始值来创建一个常量或变量。你可以用同样的方式创建一个数组。

想象一下你的配偶要求你从便利店购买一些物品。让我们使用数组来实现购物清单。将以下代码添加到你的操场中并运行它:

var shoppingList = ["Eggs", "Milk"] 

此指令创建了一个名为 shoppingList 的数组变量。分配的值 ["Eggs", "Milk"] 是一个 数组字面量。它表示一个包含两个 String 类型元素的数组,其中 "Eggs" 在索引 0"Milk" 在索引 1

在这里使用 var 关键字意味着可以修改数组的元素。由于 Swift 使用类型推断,这个数组的元素类型将是 String

假设您需要检查在商店需要购买多少个项目。在下一节中,您将学习如何确定数组中的元素数量。

检查数组中的元素数量

要找出数组中有多少个元素,请使用 count。输入并运行以下代码:

shoppingList.count 

由于 shoppingList 数组包含两个元素,结果区域显示 2

您可以使用 isEmpty 来检查数组是否为空。输入并运行以下代码:

shoppingList.isEmpty 

由于 shoppingList 数组包含两个元素,结果区域显示 false

您也可以通过使用 shoppingList.count == 0 来检查数组是否为空,但使用 shoppingList.isEmpty 提供更好的性能。

假设您的配偶打电话让您在商店时买油、鱼和鸡肉。在下一节中,您将看到如何向数组的末尾添加元素,以及在指定的数组索引处添加元素。

向数组添加新元素

您可以使用 append(_:) 方法向数组的末尾添加新元素。输入并运行以下代码:

shoppingList.append("Cooking Oil") 

"Cooking Oil" 已添加到 shoppingList 数组的末尾,该数组现在包含三个元素 – "Eggs""Milk""Cooking Oil",并且在结果区域显示为 ["Eggs", "Milk", "Cooking Oil"]

您还可以使用 + 运算符将数组添加到另一个数组中,以下代码示例:

shoppingList = shoppingList + ["Fish"] 

您可以使用 insert(_:at:) 方法在指定索引处添加新项目。输入并运行以下代码:

shoppingList.insert("Chicken", at: 1) 

这将在索引 1 处插入 "Chicken",因此现在 shoppingList 数组包含 "Eggs""Chicken""Milk""Cooking Oil""Fish"。注意,"Chicken" 是数组的第二个元素,因为第一个元素位于索引 0。您可以通过点击快速查看图标来看到这一点:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_05_02.png

图 5.2:在游乐场中显示的数组内容

假设您已经购买了购物清单上的第一个项目,现在您需要知道下一个项目是什么。在下一节中,您将学习如何使用数组索引访问特定数组元素。

访问数组元素

您可以通过指定数组索引来访问特定元素。输入并运行以下代码:

shoppingList[2] 

这将返回存储在索引 2 的数组元素,并且在结果区域显示 “Milk”

假设您的配偶打电话让您买豆浆而不是牛奶。由于这个数组是使用 var 关键字声明的,您可以修改其中存储的值。您将在下一节中学习如何操作。

将新值分配给指定索引

你可以通过指定索引并为其分配新值来替换现有的数组元素。输入并运行以下代码:

shoppingList[2] = "Soy Milk"
shoppingList 

这将替换存储在索引2处的值"Milk""Soy Milk"。现在shoppingList数组包含"Eggs""Chicken""Soy Milk""Cooking Oil""Fish",如结果区域所示。

注意,使用的索引必须是有效的。例如,你不能使用索引5,因为这里唯一的有效索引是01234。这样做会导致程序崩溃。

想象一下,你的配偶打电话告诉你冰箱里有鸡肉和鱼,所以你不再需要它们。在下一节中,你将看到两种从数组中移除元素的方法。

从数组中移除元素

你可以通过使用remove(at:)从数组中移除一个元素。输入并运行以下代码:

let oldArrayValue = shoppingList.remove(at: 1)
oldArrayValue
shoppingList 

这将从shoppingList数组中移除索引1处的项目"Chicken",因此现在它包含"Eggs""Soy Milk""Cooking Oil""Fish"。被移除的项目存储在removedValue中。你可以在结果区域中看到这一点。

你也可以选择不保留被移除的值。输入并运行以下代码:

shoppingList.remove(at:  3)
shoppingList 

这将从shoppingList数组中移除索引3处的项目"Fish",因此现在它包含"Eggs""Soy Milk""Cooking Oil"

如果你正在从数组中移除最后一个项目,你可以使用removeLast()代替,并且可以选择将移除的值也分配给一个常量或变量。

想象一下,你已经获得了列表中的每一项,并且你想再次遍历你的列表以确保。你需要依次访问每个数组元素并对每个元素执行操作。你将在下一节中看到如何做到这一点。

遍历数组

记得你在上一章中学到的for-in循环吗?你可以使用它来遍历数组中的每个元素。输入并运行以下代码:

for shoppingListItem in shoppingList {
   print(shoppingListItem)
} 

这将打印出数组中的每个元素到调试区域。

你也可以使用单侧范围运算符。这些是只有起始值的范围运算符,例如1...。输入并运行以下代码:

for shoppingListItem in shoppingList[1...] {
   print(shoppingListItem)
} 

这将在从索引1开始的数组元素打印到调试区域。

你现在知道如何使用数组创建有序列表,例如购物清单,以及如何执行数组操作,如访问、添加和移除元素。在下一节中,我们将看看如何使用字典存储无序列表的键值对。

探索字典

假设你正在编写一个联系人应用。你需要存储一个包含姓名和相应联系号码的列表。字典非常适合这个用途,因为它允许你将电话号码与联系人姓名关联起来。

字典以无序列表的形式存储键值对。它看起来是这样的:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_05_03.png

图 5.3:字典的表示

所有键必须是同一类型且必须是唯一的。所有值必须是同一类型,但不必必须是唯一的。键和值不必是同一类型的。你使用键来获取相应的值。

如果你使用 let 关键字创建字典,一旦创建,其内容就不能更改。如果你想创建后更改内容,请使用 var 关键字。

让我们看看如何与字典一起工作。你将在下一节中通过为它分配一个值来创建一个字典。

创建字典

假设你正在创建一个 联系人 应用。对于这个应用,你将使用字典来存储你的联系人。就像数组一样,你可以通过声明并为其分配一个初始值来创建一个新的字典。将以下代码添加到你的沙盒中并运行它:

var contactList = ["Shah" : "+60123456789", "Aamir" : "+0223456789"] 

此指令创建了一个名为 contactList 的字典变量。分配的值,["Shah" : "+60123456789", "Aamir" : "+0223456789"],是一个 字典字面量。它代表一个包含两个元素的字典。每个元素都是一个键值对,其中联系人名称作为键,联系人电话号码作为值。请注意,由于联系人名称是键字段,它应该是唯一的。

由于 contactList 字典是一个变量,你可以在创建后更改字典的内容。由于类型推断,键和值都是 String 类型。

假设你的应用必须显示联系人的总数。在下一节中,你将学习如何确定字典中的元素数量。

检查字典中的元素数量

要找出字典中有多少个元素,请使用 count。输入并运行以下代码:

contactList.count 

由于 contactList 字典中有两个元素,结果区域中显示 2

你可以使用 isEmpty 来检查字典是否为空。输入并运行以下代码:

contactList.isEmpty 

由于 contactList 字典有两个元素,结果区域中显示 false

也可以通过使用 contactlist.count == 0 来检查字典是否为空,但使用 contactList.isEmpty 提供了更好的性能。

假设你刚刚结束了一个会议,并想在应用中添加一个新的联系人。由于这个字典是使用 var 关键字声明的,你可以向其中添加键值对。你将在下一节中学习如何操作。

向字典中添加新元素

要向字典中添加新元素,提供一个键并为它分配一个值。输入并运行以下代码:

contactList["Meena"] = "+0229876543"
contactList 

这将在 contactList 字典中添加一个新的键值对,键为 "Meena",值为 "+0229876543"。现在它包含 "Shah" : "+60126789345""Aamir" : "+0223456789""Meena" : "+0229876543"。您可以在结果区域中看到这一点。

假设你想拨打你的一个联系人的电话,并需要该联系人的电话号码。在下一节中,你将看到如何通过指定键来访问字典元素以获取所需值。

访问字典元素

你可以指定一个字典键来访问其对应值。输入并运行以下代码:

contactList["Shah"] 

这将返回键 "Shah" 的值,并在结果区域显示 +60123456789

假设你的某个联系人换了一个新电话,因此你必须更新该联系人的电话号码。你可以修改字典中存储的键值对。你将在下一节中学习如何操作。

给现有的键分配新值

你可以给现有的键分配一个新值。输入并运行以下代码:

contactList["Shah"] = "+60126789345"
contactList 

这将给键 "Shah" 分配一个新值。现在 contactList 字典包含 "Shah" : "+60126789345""Aamir" : "+0223456789""Meena" : "+0229876543"。你可以在结果区域看到这一点。

假设你必须从你的应用程序中删除一个联系人。让我们看看下一节中如何从字典中移除元素。

从字典中移除元素

要从字典中移除一个元素,将 nil 分配给现有的键。输入并运行以下代码:

contactList["Aamir"] = nil
contactList 

这将从 contactList 字典中移除键为 "Aamir" 的元素,现在它包含 "Shah" : "+60126789345""Meena" : "+0229876543"。你可以在结果区域看到这一点。

如果你想要保留你正在移除的值,请使用 removeValue(for:Key) 代替。输入并运行以下代码:

var oldDictValue = contactList.removeValue(forKey: "Meena")
oldDictValue
contactList 

这将从 contactList 字典中移除键为 "Meena" 的元素,并将其值分配给 oldDictValue。现在 oldDictValue 包含 "+0229876543",而 contactList 字典包含 "Shah" : "+60126789345"

你也可以选择只移除值,而无需将其分配给常量或变量,如下所示:

contactList.removeValue(forKey: "Meena") 

假设你想要给每个联系人打电话,祝他们新年快乐。你必须依次访问每个字典元素并对其执行操作。你将在下一节中看到如何操作。

遍历字典

就像数组一样,你可以使用 for-in 循环遍历字典中的每个元素。输入并运行以下代码:

for (name, contactNumber) in contactList {
   print("\(name) : \(contactNumber)")
} 

这将打印字典中的每个元素到调试区域。由于字典是无序的,当你再次运行此代码时,你可能会得到不同的结果顺序。

现在你已经知道如何使用字典创建一个无序的键值对列表,例如联系人列表,以及如何执行字典操作。在下一节中,我们将看看如何在一个集合中存储无序的值列表。

探索集合

假设你正在编写一个 Movies 应用程序,并想存储电影类型列表。你可以使用集合来完成这个任务。

集合以无序列表的形式存储值。它看起来是这样的:

https://github.com/OpenDocCN/freelearn-mobi-zh/raw/master/docs/ios18-prog-bgn/img/B31371_05_04.png

图 5.4:集合的表示

所有值都是同一类型。

如果你使用 let 关键字创建一个集合,其内容在创建后不能被更改。如果你想创建后更改内容,请使用 var 关键字。

让我们看看如何处理集合。你将在下一节中通过给它赋值来创建一个集合。

创建集合

想象一下,你正在创建一个 电影 应用,并且你希望在你的应用中存储电影类型。该应用将存储你喜欢的电影类型,并且它可以检查你想要观看的电影是否在其中。与数组相比,集合是无序的并且只包含唯一值,而数组是有序的,按索引排列,可以包含重复值。由于你不需要按顺序存储电影类型,并且每个类型都是唯一的,因此你将使用集合来完成这个目的。

正如你所看到的,对于数组和字典,你可以通过声明它并分配一个新的值来创建一个集合。将以下代码添加到你的游乐场中并运行它:

var movieGenres: Set = ["Horror", "Action", "Romantic Comedy" ] 

这个指令创建了一个名为 movieGenres 的集合变量。请注意,分配给它的 集合字面量 ["Horror", "Action", "Romantic Comedy"] 与数组字面量的格式相同,因此你使用类型注解将 movieGenres 的类型设置为 Set。否则,Swift 的类型推断将创建一个数组变量而不是集合变量。

在这里使用 var 关键字意味着集合的内容可以被修改。由于类型推断,这个集合的元素类型将是 String

想象一下,你需要显示你应用中电影类型的总数。让我们看看如何在下一节中找到集合中元素的数量。

检查集合中的元素数量

要找出集合中有多少个元素,请使用 count。输入并运行以下代码:

movieGenres.count 

由于 movieGenres 集合包含三个元素,结果区域显示 3

你可以使用 isEmpty 来检查一个集合是否为空。输入并运行以下代码:

movieGenres.isEmpty 

由于 movieGenres 包含三个元素,结果区域显示 false

你也可以通过使用 movieGenres.count == 0 来检查集合是否为空,但使用 movieGenres.isEmpty 提供更好的性能。

想象一下,你的应用的用户可以添加更多类型。由于这个集合是使用 var 关键字声明的,你可以向其中添加元素。你将在下一节中学习如何操作。

向集合中添加新元素

你可以通过使用 insert(_:) 来向集合中添加新元素。输入并运行以下代码:

movieGenres.insert("War")
movieGenres 

这将一个新的项目 "War" 添加到 movieGenres 集合中,现在它包含 "Horror""Romantic Comedy""War""Action"。当你点击快速查看图标时,这一点是可见的。

想象一下,一个用户想知道你的应用中是否提供某种类型的电影。在下一节中,你将学习如何检查一个元素是否在集合中。

检查集合是否包含一个元素

要检查集合是否包含一个元素,请使用 contains(_:)。输入并运行以下代码:

movieGenres.contains("War") 

由于 "War"movieGenres 集合中的一个元素,结果区域显示 true

假设一个用户想要从他们的音乐类型列表中移除一个类型。让我们在下一节中看看如何从集合中移除不再需要的项。

从集合中移除项

要从集合中移除项,请使用 remove(_:)。你正在移除的值可以被丢弃、赋值给变量或常量。如果该值不存在于集合中,则返回 nil。输入并运行以下代码:

var oldSetValue = movieGenres.remove("Action")
oldSetValue
movieGenres 

"动作"movieGenres 集合中移除并赋值给 oldSetValue,现在 movieGenres 集合包含 "恐怖"、“浪漫喜剧” 和 "战争"

要从集合中移除所有元素,请使用 removeAll()

假设你希望显示你应用中所有音乐类型作为你应用用户的推荐。你可以遍历并操作每个集合元素。让我们在下一节中看看如何做到这一点。

遍历集合

与数组和大纲类似,你可以使用 for-in 循环遍历集合中的每个元素。输入并运行以下代码:

for genre in movieGenres {
   print(genre)
} 

你应该在调试区域看到每个集合元素。由于集合是无序的,当你再次运行此代码时,你可能会得到不同的结果顺序。

假设你想让你的应用对你喜欢的音乐类型和另一个人喜欢的音乐类型执行操作。在下一节中,你将了解在 Swift 中可以使用集合执行的各种操作。

执行集合操作

执行集合操作,如 并集交集减集对称差集 非常简单。输入并运行以下代码:

let movieGenres2: Set = ["Science Fiction", "War", "Fantasy"]
movieGenres.union(movieGenres2)
movieGenres.intersection(movieGenres2)
movieGenres.subtracting(movieGenres2)
movieGenres.symmetricDifference(movieGenres2) 

在这里,你正在对两个集合 movieGenresmovieGenres2 执行集合操作。让我们看看每个集合操作的结果:

  • union(_:) 返回一个新集合,包含两个集合中的所有值,因此当你点击快速查看图标时,会显示 “恐怖”,“浪漫喜剧”,“战争”,“科幻”“奇幻”

  • intersection(_:) 返回一个新集合,其中只包含两个集合共有的值,因此当你点击快速查看图标时,会显示 “战争”

  • subtracting(_:) 返回一个新集合,不包含指定集合中的值,因此当你点击快速查看图标时,会显示 “恐怖”“浪漫喜剧”

  • symmetricDifference(_:) 返回一个新集合,不包含两个集合共有的值,因此当你点击快速查看图标时,会显示 “恐怖”,“浪漫喜剧”,“科幻”“奇幻”

假设你想让你的应用比较你喜欢的音乐类型和另一个人喜欢的音乐类型。在下一节中,你将学习如何检查一个集合是否等于另一个集合,是否是另一个集合的子集,或者与另一个集合没有任何共同点。

理解集合成员资格和相等性

检查一个集合是否等于另一个集合的 子集超集不相交 非常简单。输入并运行以下代码:

let movieGenresSubset: Set = ["Horror", "Romantic Comedy"]
let movieGenresSuperset: Set = ["Horror", "Romantic Comedy", "War", "Science Fiction", "Fantasy"]
let movieGenresDisjoint: Set = ["Bollywood"]
movieGenres == movieGenres2
movieGenresSubset.isSubset(of: movieGenres)
movieGenresSuperset.isSuperset(of: movieGenres)
movieGenresDisjoint.isDisjoint(with: movieGenres) 

让我们看看这段代码是如何工作的:

  • == 操作符检查一个集合的所有成员是否与另一个集合的成员相同。由于 movieGenres 集合的所有成员并不都与 movieGenres2 集合的成员相同,结果区域将显示 false

  • isSubset(of:) 检查一个集合是否是另一个集合的子集。由于 movieGenresSubset 集合的所有成员都在 movieGenres 集合中,结果区域将显示 true

  • isSuperset(of:) 检查一个集合是否是另一个集合的超集。由于 movieGenres 集合的所有成员都在 movieGenresSuperset 集合中,结果区域将显示 true

  • isDisjoint(with:) 检查一个集合是否与另一个集合没有共同的值。由于 movieGenresDisjoint 集合与 movieGenres 集合没有共同的成员,结果区域将显示 true

你现在知道如何使用集合来创建一个无序的值列表,例如电影类型的列表,以及如何执行集合操作。这标志着关于集合类型的章节结束。做得好!

摘要

在本章中,你学习了 Swift 中的集合类型。首先,你学习了有关数组的内容。这些允许你使用有序的值列表来表示如购物清单这样的项目,并对它执行操作。

接下来,你学习了有关字典的内容。这些允许你使用无序的键值对列表来表示如联系人列表这样的项目,并对它执行操作。

最后,你学习了有关集合的知识。这些允许你使用无序的值列表来表示如电影类型列表这样的项目,并对它执行操作。你还学习了为什么在这种情况下使用集合而不是数组可能更合适。

在下一章中,你将学习如何使用函数将一组指令组合在一起。当你想在程序中多次执行一组指令时,这非常有用。

加入我们的 Discord 社区!

与其他用户、专家以及作者本人一起阅读这本书。提问、为其他读者提供解决方案、通过“问我任何问题”的环节与作者聊天,以及更多。扫描二维码或访问链接加入社区。

packt.link/ios-Swift

https://packt.link/ios-Swift

第六章:函数和闭包

到目前为止,你可以编写相对复杂的程序,这些程序可以做出决策并重复指令序列。你还可以使用集合类型为你的程序存储数据。随着你编写的程序在大小和复杂性上增长,理解它们所做的工作将变得更加困难。

为了使大型程序更容易理解,Swift 允许你创建函数,这让你可以通过调用单个名称来组合多个指令并执行它们。你还可以创建闭包,这让你可以组合多个指令而不命名,并将它们分配给常量或变量。

到本章结束时,你将了解函数、嵌套函数、作为返回类型的函数、作为参数的函数以及guard语句。你还将了解如何创建和使用闭包。

本章将涵盖以下主题:

  • 探索函数

  • 探索闭包

技术要求

本章的 Xcode 游乐场位于本书代码包的Chapter06文件夹中,可以在此处下载:

github.com/PacktPublishing/iOS-18-Programming-for-Beginners-Ninth-Edition

查看以下视频,看看代码的实际效果:

youtu.be/lgPDkddf_tc

如果你希望从头开始,创建一个新的游乐场,并将其命名为FunctionsAndClosures

你可以在进行过程中输入并运行本章中的所有代码。让我们先了解函数。

探索函数

函数对于封装执行特定任务的多个指令非常有用,如下所示:

  • 计算餐厅餐费的 10%服务费

  • 计算你希望购买的汽车的月供

这就是函数的样子:

func functionName(parameter1: ParameterType, ...) -> ReturnType {
  code
} 

每个函数都有一个描述性的名称。你可以定义一个或多个作为输入值的函数,这些值被称为参数。你还可以定义函数完成后的输出,这被称为其返回类型。参数和返回类型都是可选的。

你“调用”函数的名称来执行它。这就是函数调用的样子:

functionName(parameter1: argument1,) 

你提供与函数参数类型匹配的输入值(称为参数)。

要了解更多关于函数的信息,请访问docs.swift.org/swift-book/documentation/the-swift-programming-language/functions/

在下一节中,我们将看看如何创建一个函数来计算服务费。

创建函数

在其最简单的形式中,函数只是执行一些指令,没有任何参数或返回类型。你将通过编写一个计算餐费服务费的函数来了解这是如何工作的。服务费应该是餐费的 10%。

将以下代码添加到你的游乐场中,创建并调用此函数并运行它:

func serviceCharge() {
  let mealCost = 50
  let serviceCharge = mealCost / 10
  print("Service charge is \(serviceCharge)")
}
serviceCharge() 

你刚刚创建了一个名为serviceCharge()的非常简单的函数。它所做的只是计算价值 50 美元的餐费的 10%服务费,即50 / 10,返回5。然后你使用其名称调用此函数。你将在调试区域看到服务费是 5的显示。

这个函数不是很实用,因为每次调用这个函数时mealCost总是50。此外,结果只打印在调试区域,不能在程序的其他地方使用。让我们给这个函数添加一些参数和一个返回类型,使其更有用。

按照以下所示修改你的代码:

func serviceCharge(**mealCost****:** **Int****) ->** **Int**{
  **return** **mealCost** **/****10**
}
**let****serviceChargeAmount****=****serviceCharge****(****mealCost****:** **50****)**
**print(****serviceChargeAmount****)** 

这样就更好了。现在,你可以在调用serviceCharge(mealCost:)函数时设置餐费,并将结果分配给一个变量或常量。尽管这样看起来有点别扭。你应该尝试使 Swift 中的函数签名读起来像英语句子,因为这被认为是一种最佳实践。让我们看看如何在下一节中做到这一点,你将使用自定义标签使你的函数更符合英语风格,更容易理解。

使用自定义参数标签

注意,serviceCharge(mealCost:)函数不太符合英语风格。你可以给参数添加一个自定义标签,使函数更容易理解。

按照以下所示修改你的代码:

func serviceCharge(**forMealPrice** mealCost: Int) -> Int {
  mealCost / 10
}
let serviceChargeAmount = serviceCharge(**forMealPrice**: 50)
print(serviceChargeAmount) 

函数的工作方式与之前相同,但调用它时,你使用serviceCharge(forMealPrice:)。这听起来更像是英语,更容易弄清楚函数的作用。此外,注意如果你的函数体只包含一个语句,则return关键字是可选的。

在下一节中,你将学习如何在其他函数体内使用几个较小的函数,这些被称为嵌套函数

使用嵌套函数

在另一个函数体内有一个函数,这些被称为嵌套函数。这允许你将多个相关函数放在一起,使封装函数更容易理解。

嵌套函数可以使用封装函数的变量。让我们通过编写一个计算贷款月供的函数来了解嵌套函数是如何工作的。

输入并运行以下代码:

func calculateMonthlyPayments(carPrice: Double, downPayment: Double, interestRate: Double, paymentTerm: Double) -> Double {
  func loanAmount() -> Double {
    carPrice - downPayment
  }
  func totalInterest() -> Double {
    interestRate * paymentTerm
  }
  func numberOfMonths() -> Double {
    paymentTerm * 12
  }
  return ((loanAmount() + (loanAmount() *
  totalInterest() / 100 )) / numberOfMonths())
}
calculateMonthlyPayments(carPrice: 50000, downPayment: 5000, interestRate: 3.5, paymentTerm: 7.0) 

这里,在calculateMonthlyPayments(carPrice:downPayment:interestRate:paymentTerm:)中有三个函数。让我们来看看它们:

  • 第一个嵌套函数loanAmount()通过从carPrice中减去downPayment来计算总贷款金额。它返回50000 - 5000 = 45000

  • 第二个嵌套函数totalInterest()通过将interestRate乘以paymentTerm来计算支付期限产生的总利息金额。它返回3.5 * 7 = 24.5

  • 第三个嵌套函数numberOfMonths()通过将paymentTerm乘以12来计算支付期限的总月份数。它返回7 * 12 = 84

注意,三个嵌套函数都使用了封装函数的变量。返回的值是 ( 45000 + ( 45000 * 24.5 / 100 ) ) / 84 = 666.96,这是您为了购买这辆车每月必须支付的金额。

如您所见,Swift 中的函数与其他语言中的函数类似,但有一个酷炫的特性。在 Swift 中,函数是一等类型,因此它们可以用作参数和返回类型。让我们在下一节中看看这是如何实现的。

使用函数作为返回类型

一个函数可以作为其返回类型返回另一个函数。输入并运行以下代码以创建一个函数,该函数使用两种可能的方法之一生成π的值:

func approximateValueOfPi1() -> Double {
  3.14159
}
func approximateValueOfPi2() -> Double {
  22.0 / 7.0
}
func pi() -> (() -> Double) {
  approximateValueOfPi1
  // approximateValueOfPi2
}
pi()() 

approximateValueOfPi1()approximateValueOfPi2() 都是没有任何参数并返回π近似值的函数。pi() 函数的返回类型是一个没有参数并返回 Double 类型的函数。这意味着它可以返回 approximateValueOfPi1(如所示)或 approximateValueOfPi2,因为这两个函数都符合预期的返回类型。

pi()() 调用了返回 3.14159 的函数 approximateValueOfPi13.14159 在结果区域中显示。

让我们看看在下一节中如何将一个函数用作另一个函数的参数。

使用函数作为参数

一个函数可以将另一个函数作为参数。输入并运行以下代码以创建一个函数,该函数用于判断一个满足特定条件的数字是否存在于数字列表中:

func isThereAMatch(listOfNumbers: [Int], condition: (Int) -> Bool) -> Bool {
  for number in listOfNumbers {
    if condition(number) {
      return true
    }
  }
  return false
}
func numberIsOdd(number: Int) -> Bool {
  (number % 2) > 0
}
func numberIsEven(number: Int) -> Bool {
  (number % 2) == 0
}
let numbersList = [1, 3, 5, 7]
isThereAMatch(listOfNumbers: numbersList, condition: numberIsOdd) 

isThereAMatch(listOfNumbers:condition:) 有两个参数:一个整数数组和函数。提供的作为参数的函数必须接受一个整数值并返回一个布尔值。

numberIsOdd(number:)numberIsEven(_:) 都接受一个整数并返回一个布尔值,这意味着任一函数都可以作为第二个参数的参数。包含奇数的数组 numbersList 用作第一个参数的参数。当 numberIsOdd 作为第二个参数的参数时,isThereAMatch(listOfNumbers:condition:) 被调用时会返回 true。尝试使用 numberisEven 作为第二个参数的参数。

函数作为参数和返回类型可能难以理解,但在您学习旅程的这个阶段相对较少,所以如果您一开始不理解,请不要担心。随着您经验的积累,这会变得更容易理解。

在下一节中,您将了解如果使用的参数不合适,如何从函数中提前退出。

使用守卫语句提前退出函数

假设您需要一个函数用于在线购物终端。这个函数将在您购买东西时计算借记卡或信用卡的剩余余额。您想要购买的物品价格输入在一个文本字段中。

文本框中的值被转换为整数,这样你就可以计算剩余的卡余额。如果输入数据有问题,能够提前退出函数是非常有用的。

输入并运行以下代码:

func buySomething(itemValueEntered itemValueField: String, cardBalance: Int) -> Int {
  guard let itemValue = Int(itemValueField) else {
    print("Error in item value")
    return cardBalance
  }
  let remainingBalance = cardBalance - itemValue
  return remainingBalance
}
print(buySomething(itemValueEntered: "10", cardBalance: 50))
print(buySomething(itemValueEntered: "blue", cardBalance: 50)) 

你应该在调试区域看到这个结果:

40
Error in item value
50 

让我们看看这个函数是如何工作的。函数体内的第一行是一个guard语句。这个语句检查一个条件是否为true;如果不是,它将退出函数。在这里,它被用来检查用户是否在在线购买终端输入了有效的价格。

如果是这样,该值可以成功转换为整数,你可以计算剩余的卡余额。否则,guard语句中的else子句将被执行。错误信息将被打印到调试区域,并且返回未更改的卡余额。

对于print(buySomething(itemValueEntered: "10", cardBalance: 50)),项目价格成功从卡余额中扣除,并返回40

对于print(buySomething(itemValueEntered: "blue", cardBalance: 50))guard语句的条件失败,其else子句被执行,导致错误信息被打印到调试区域,并返回50

现在,你已经知道了如何创建和使用函数。你还看到了如何使用自定义参数标签、嵌套函数、函数作为参数或返回类型,以及guard语句。

现在,让我们看看闭包。与函数一样,闭包允许你组合多个指令,但闭包没有名字,并且可以被分配给一个常量或变量。你将在下一节中看到它们是如何工作的。

探索闭包

闭包,就像函数一样,包含一系列指令,可以接受参数并返回值。然而,闭包没有名字。闭包中的指令序列被大括号({ })包围,in关键字将参数和返回类型与闭包体分开。

闭包可以被分配给一个常量或变量,所以当你需要在程序内部传递它们时,它们非常方便。例如,假设你有一个从互联网下载文件的应用程序,并且你需要在文件下载完成后对文件进行一些操作。你可以在闭包内部放置一个处理文件的指令列表,并在文件下载完成后让程序执行它。

要了解更多关于闭包的信息,请访问docs.swift.org/swift-book/documentation/the-swift-programming-language/closures/

你现在将编写一个闭包,该闭包将对数字数组中的每个元素应用计算。将以下代码添加到你的游乐场中,然后点击运行按钮来运行它:

var numbersArray = [2, 4, 6, 7]
let myClosure = { (number: Int) -> Int in
   let result = number * number
   return result
}
let mappedNumbers = numbersArray.map(myClosure) 

这将一个计算数字的平方的闭包赋值给 myClosure。然后 map() 函数将此闭包应用于 numbersArray 中的每个元素。每个元素都乘以自身,并在结果区域出现 [4, 16, 36, 49]

您可以以更简洁的方式编写闭包,您将在下一节中看到如何做到这一点。

简化闭包

新开发者遇到困难的一件事是经验丰富的 Swift 程序员编写闭包时使用的非常简洁的方法。考虑以下示例中的代码:

var testNumbers = [2, 4, 6, 7]
let mappedTestNumbers = testNumbers.map({ 
  (number: Int) -> Int in
  let result = number * number
  return result
})
print(mappedTestNumbers) 

在这里,您有 testNumbers,一个数字数组,您使用 map(_:) 函数依次将闭包映射到数组的每个元素。闭包中的代码将数字乘以自身,生成该数字的平方。结果 [4, 16, 36, 49] 然后打印到调试区域。您将看到,闭包代码可以写得更加简洁。

当闭包的类型已知时,您可以删除参数类型、返回类型或两者。单行闭包隐式返回其唯一语句的值,这意味着您可以删除 return 语句。因此,您可以按如下方式编写闭包:

let mappedTestNumbers = testNumbers.map({ number in
  number * number
}) 

当闭包是函数的唯一参数时,您可以省略包围闭包的括号,如下所示:

let mappedTestNumbers = testNumbers.map { number in
  number * number
} 

您可以使用表示它们在参数列表中相对位置的数字来引用参数,而不是使用名称,如下所示:

let mappedTestNumbers = testNumbers.map { $0 * $0 } 

因此,闭包现在确实非常简洁,但对于新开发者来说可能难以理解。请随意以您舒适的方式编写闭包。

您现在已经知道如何创建和使用闭包,以及如何更简洁地编写它们。太棒了!

概述

在本章中,您学习了如何将语句分组到函数中。您学习了如何使用自定义参数标签、函数内的函数、函数作为返回类型、函数作为参数以及 guard 语句。当您需要在程序的不同点完成相同任务时,这将很有用。

您还学习了如何创建闭包。当您需要在程序中传递代码块时,这将很有用。

在下一章中,我们将研究类、结构和枚举。类和结构允许创建可以存储状态和行为复杂对象,枚举可以用来限制可以分配给变量或常量的值,从而减少出错的可能性。

加入我们的 Discord!

与其他用户、专家和作者本人一起阅读这本书。提出问题,为其他读者提供解决方案,通过 Ask Me Anything 会话与作者聊天,等等。扫描二维码或访问链接加入社区。

packt.link/ios-Swift

https://packt.link/ios-Swift

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值