欢迎光临散文网 会员登陆 & 注册

SwiftUI学习100天(Day81 - 项目 16,第三部分)

2023-03-26 12:00 作者:爱上树の蜗牛  | 我要投稿

原创链接:https://www.hackingwithswift.com/100/swiftui

以下内容仅供学习参考:

今天我们将研究三个重要功能:SwiftUI 中的上下文菜单、iOS 中的通知和 Xcode 中的 Swift 包依赖项。这是应用程序开发人员需要掌握的另外三个真正关键的功能,我希望你会发现所有这些功能都相对容易学习。

上下文菜单——当你在 iOS 中按住某些东西时弹出的菜单——允许我们为布局中的视图添加额外的操作。这是避免给你的 UI 添加混乱的好方法,但我希望你在这样做时要谨慎行事。Scott Belsky 曾是 Adobe 的副总裁,现在是风险投资家,他曾经说过,设计良好的用户体验有一条规则:“更多选择,更多问题。”

因此,一定要为你的 UI 添加额外的功能,但始终要考虑可发现性。毕竟,如果用户找不到你的操作,那么它们可能就不存在了!

今天,你需要完成三个主题,你将在其中了解上下文菜单、本地通知、Swift 包依赖项等。

创建上下文菜单

当用户点击按钮或导航链接时,很明显 SwiftUI 应该触发这些视图的默认操作。但是,如果他们按住某物怎么办?在旧版 iPhone 上,用户可以通过用力按压某物来触发 3D Touch,但原理是一样的:用户想要与他们交互的任何东西都有更多选择。

SwiftUI 允许我们将上下文菜单附加到对象以提供这种额外的功能,所有这些都是使用contextMenu()修饰符完成的。你可以将选择的按钮传递给它,它们将按顺序显示,因此我们可以构建一个简单的上下文菜单来控制视图的背景颜色,如下所示:


就像 TabView一样,上下文菜单中的每个项目都可以使用Label视图附加文本和图像。

现在,这里有一个问题:为了让用户界面在应用程序中看起来有些统一,iOS 将每个图像呈现为纯色,其中保留了不透明度。这使得许多图片变得毫无用处:如果你有三张不同狗的三张照片,所有三张图片都会呈现为纯黑色方块,因为所有颜色都被移除了。

相反,你应该瞄准线条艺术图标,例如 Apple 的 SF Symbols,如下所示:

当你运行它时,你会看到foregroundColor()修改器被忽略了——iOS 确实希望我们的菜单看起来统一,所以试图随机给它们上色是行不通的。如果你真的希望该项目显示为红色,你应该知道这意味着破坏性,你应该改用按钮角色:

在使用上下文菜单时,我为你提供了一些提示,以帮助确保你为用户提供最佳体验:

  1. 如果你要使用它们,请在很多地方使用它们——如果按住某个东西却发现什么也没有发生,这可能会令人沮丧。

  2. 使你的选项列表尽可能短——目标是三个或更少。

  3. 不要重复用户已经可以在 UI 的其他地方看到的选项。

请记住,上下文菜单本质上是隐藏的,因此在将重要操作隐藏在上下文菜单中之前请三思。

将自定义行滑动操作添加到列表

从我记事起,iOS 应用程序就具有“滑动删除”功能,但近年来它们的功能越来越强大,因此列表行可以有多个按钮,通常位于行的两侧。我们使用修饰符在 SwiftUI 中获得了这个完整的功能swipeActions(),它允许我们在列表行的一侧或两侧注册一个或多个按钮。

默认情况下按钮将放置在行的右边缘,并且不会有任何颜色,因此当你从右向左滑动时将显示一个灰色按钮:

你可以通过向修改器swipeActions()提供edge参数来自定义放置按钮的边缘,并且可以通过向按钮添加tint()你选择的颜色的修改器或附加按钮角色来自定义按钮的颜色。

因此,这将在我们行的两侧显示一个按钮:

与上下文菜单一样,滑动操作本质上默认对用户是隐藏的,因此不要在其中隐藏重要功能很重要。我们将在此应用程序中同时使用它们,希望你有机会直接比较和对比它们!

安排本地通知

iOS 有一个名为 UserNotifications 的框架,它几乎完全符合你的期望:让我们为用户创建可以在锁定屏幕上显示的通知。我们有两种类型的通知可以使用,它们根据创建位置的不同而有所不同:本地通知是我们在本地安排的通知,远程通知(通常称为推送通知)是从某处服务器发送的。

远程通知需要服务器才能工作,因为你将消息发送到 Apple 的推送通知服务 (APNS),然后由后者将其转发给用户。但是相比之下,本地通知要好得多,也容易一些,因为只要用户允许,我们可以随时发送任何消息。

要尝试这个,首先在 ContentView.swift 的顶部附近添加一个额外的导入:

接下来我们将放入一些我们将用本地通知代码填充的基本结构。使用本地通知需要请求用户许可,然后实际注册我们要显示的通知。我们会将这些操作中的每一个放入一个VStack内的单独按钮中,因此请现在将其放入你的ContentView结构体中:

好的,我们的设置已经完成,所以让我们将注意力转移到两个重要工作中的第一个:请求授权以显示警报。通知可以采用多种形式,但最常见的做法是请求显示警报、徽章和声音的许可——这并不意味着我们需要同时使用所有这些,而是预先请求许可意味着我们以后可以有选择。

当我们告诉 iOS 我们想要什么样的通知时,它会向用户显示一个提示,这样他们对我们的应用程序可以做什么有最终决定权。当他们做出选择时,我们提供的闭包将被调用并告诉我们请求是否成功。

所以,用这个替换评论// first

如果用户授予权限,那么我们就可以开始安排通知了。尽管通知可能看起来很简单,但 Apple 将它们分为三个部分以提供最大的灵活性:

  • 内容是应该显示的内容,可以是标题、副标题、声音、图像等。

  • 触发器确定何时应显示通知,可以是从现在开始的秒数、未来的日期和时间或位置。

  • 该请求结合了内容和触发器,还添加了一个唯一标识符,以便你稍后可以编辑或删除特定警报。如果你不想编辑或删除内容,请使用UUID().uuidString获取随机标识符。

当你刚开始学习通知时,最容易使用的触发器类型是UNTimeIntervalNotificationTrigger,它允许我们请求在从现在起的特定秒数后显示通知。所以,用这个替换评论// second

如果你现在运行呢的应用程序,请按第一个按钮请求通知权限,然后按第二个按钮添加实际通知。

现在是重要的部分:添加通知后,在模拟器中按 Cmd+L 锁定屏幕。几秒钟后,设备应该会被声音唤醒,并显示我们的消息——很好!

在 Xcode 中添加 Swift 包依赖

到目前为止我们编写的所有代码都是我们从头开始构建的东西,因此你可以确切地看到它是如何工作的并将这些技能应用到你自己的项目中。但有时,从头开始编写一些东西是有风险的:也许代码很复杂,也许很容易出错,也许它经常更改,或者任何其他无数原因,这就是存在依赖关系的原因——获取第三方代码的能力并在我们的项目中使用它。

Xcode 内置了一个依赖管理器,称为 Swift Package Manager (SPM)。你可以告诉 Xcode 一些在线存储的代码的 URL,它会为你下载。你甚至可以告诉它要下载哪个版本,这意味着如果远程代码在将来某个时候发生更改,你可以确保它不会破坏你现有的代码。

为了尝试这一点,我创建了一个简单的 Swift 包,你可以将其导入到任何项目中。这为 Swift 的Sequence类型(ArraySetDictionary甚至范围都符合)添加了一个小的扩展,可以同时抽取一些随机项。

不管怎样,第一步是将包添加到我们的项目中:转到“文件”菜单并选择“添加包”。对于 URL,请输入https://github.com/twostraws/SamplePackage,这是我的示例包的代码存储位置。Xcode 将获取包,读取其配置,并向你显示选项,询问你要使用哪个版本。默认值为“Version – Up to Next Major”,这是最常用的版本,意味着如果包的作者将来更新它,那么只要他们不引入重大更改,Xcode 就会更新包使用新版本。

这是可能的原因是因为大多数开发人员已经同意为其代码使用语义版本控制系统 (SemVer)。如果你查看像 1.5.3 这样的版本,那么 1 被认为是主要编号,5 被认为是次要编号,而 3 被认为是补丁编号。如果开发人员正确遵循 SemVer,那么他们应该:

  • 只要不破坏任何 API 或添加功能,在修复错误时更改补丁号。

  • 当他们添加不破坏任何 API 的功能时更改次要编号。

  • 当他们破坏 API时更改主编号。

这就是“Up to Next Major”如此有效的原因,因为它应该意味着随着时间的推移你会获得新的错误修复和功能,但不会意外切换到破坏你代码的版本。

无论如何,我们已经完成了我们的包,所以单击 Finish 让 Xcode 将它添加到项目中。你应该会看到它出现在项目导航器中的“Swift Package Dependencies”下。

要尝试一下,请打开 ContentView.swift 并将此导入添加到顶部:

是的,这个外部依赖现在是一个模块,我们可以在任何需要的地方导入它。

现在我们可以在我们的视图中尝试它。例如,我们可以通过制作从 1 到 60 的数字范围来模拟一个简单的彩票,从中挑选 7 个,将它们转换为字符串,然后将它们连接成一个字符串。简而言之,这将需要一些你以前从未见过的代码,因此我将对其进行分解。

首先,用这个替换你的ContentView

是的,那是行不通的,因为results不见了,但我们现在要填补它。

首先,可以通过将此属性添加到 ContentView来创建从 1 到 60 的数字范围

其次,我们将创建一个名为results的计算属性,它从那里挑选七个数字并将它们变成一个字符串,因此也添加这个属性:

在里面,我们将从我们的范围中选择七个随机数,这可以使用你从我的 SamplePackage 框架中获得的扩展来完成。这提供了一种random()方法,该方法接受一个整数并将以随机顺序从你的序列中返回最多该数量的随机元素。彩票号码通常是从小到大排列的,所以我们要对它们进行排序。

因此,添加这行代码代替// more code to come

接下来,我们需要将该整数数组转换为字符串。这在 Swift 中只需要一行代码,因为序列有一个map()方法可以让我们通过对每个元素应用一个函数将一种类型的数组转换为另一种类型的数组。在我们的例子中,我们想从每个整数初始化一个新的字符串,这样我们就可以用作String.init我们想要调用的函数。

因此,在上一行之后添加这一行:

此时strings是一个字符串数组,其中包含我们范围内的七个随机数,因此最后一步是将它们全部连接在一起,中间用逗号分隔。现在将最后一行添加到属性中:

这就完成了我们的代码:文本视图将显示里面的值results,它将继续选择随机数,对它们进行排序,将它们字符串化,然后用逗号连接它们。

PS:你可以直接在 Xcode 中阅读我的简单扩展的源代码——只需打开 Sources > SamplePackage 组并查找 SamplePackage.swift。你会发现它并没有多大作用!

这完成了该项目所需的最终技术,因此请将你的代码重置为原始状态。


SwiftUI学习100天(Day81 - 项目 16,第三部分)的评论 (共 条)

分享到微博请遵守国家法律