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

SwiftUI学习100天(Day96 - 项目 19,第一部分)

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

尽管到目前为止我们所有的项目都在 iPad 上能够运行,但我们并没有真正花时间停下来深入研究它。好吧,这在我们的新项目中发生了变化,因为我们将构建一个应用程序,利用 iPad 提供的所有额外空间,甚至利用 Max-sized iPhone 横向提供的空间。

尽管 Apple 在 2019 年将 iOS 分叉为 iPadOS,但 iPad 和 iPhone 在软件方面几乎完全相同。这意味着我们可以编写同时在两个平台上运行的代码,只需进行少量更改即可真正充分利用每个环境。

史蒂夫·乔布斯 (Steve Jobs) 在 2010 年推出第一款 iPad 时说,“因为我们已经出货了超过 7500 万部 iPhone,所以已经有 7500 万用户知道如何使用 iPad。” 这意味着用户也可以从两个平台的相似性中受益,因为他们可以立即知道如何在 iPad 上使用我们的应用程序,这要归功于 iPhone 上的现有用法。

尽管自定义用户界面看起来和感觉起来都很棒,但永远不要低估这种内置知识的力量!

今天你有四个主题要完成,在这些主题中你将学习拆分视图控制器、将弹窗绑定到可选类型以及使用组进行灵活布局。

SnowSeeker:简介

在这个项目中,我们将创建 SnowSeeker:一款让用户浏览世界各地滑雪胜地的应用程序,帮助他们找到适合下一个假期的滑雪胜地。

这将是我们专门致力于通过并排显示两个视图来制作在 iPad 上运行良好的应用程序的第一款应用程序,但你还将深入解决有问题的布局,学习一种显示工作表和弹窗的新方法等等.

与往常一样,在进入主项目之前我们需要介绍一些技术,因此请使用 App 模板创建一个新的 iOS 项目,将其命名为 SnowSeeker。

我们走!


在 SwiftUI 中使用两个并排视图

你可能没有意识到,但我们的应用程序适应不同屏幕尺寸的最聪明、最简单的方法之一实际上已经融入到NavigationView.

你已经熟悉 NavigationView的基本用法,这使我们能够创建这样的视图:

但是,你在运行时看到的内容取决于几个因素。如果你正在纵向使用 iPhone,那么你会看到你所期望的布局:顶部有一个大的“主要”标题,然后是一个小的“Hello,world!” 以下方空间为中心。

如果你将同一部手机旋转到横向,那么你会看到以下两种情况之一:在大多数 iPhone 上,导航标题会缩小为小文本,以便占用更少的空间,但在最大尺寸的 iPhone 上,例如在 iPhone 13 Pro Max 上,你会看到我们的标题在左上角变成了一个蓝色按钮,使屏幕的其余部分保持清晰。点击那个按钮就会出现“你好,世界!” 文本从前缘滑入,你还会在顶部看到“主要”标题。

在 iPad 上,事情变得更加聪明,因为系统会根据设备的大小和可用的屏幕空间从三种不同的布局中进行选择。例如,如果我们横向使用 12.9 英寸的 iPad Pro,那么:

  1. 如果我们的应用程序拥有整个屏幕,你将看到“Hello, world!” 视图在左侧可见,右侧没有任何内容。

  2. 如果应用程序的空间非常小,它看起来就像一个纵向的长 iPhone。

  3. 对于其他大小,你可能会看到“主要”按钮可见,这会导致“Hello, world!” 按下时滑入的文本。

你在这里看到的称为自适应布局,它用于 Apple 的许多应用程序,例如 Notes、Mail 等。它允许 iOS 充分利用可用的屏幕空间,而无需我们参与。

这里实际发生的是 iOS 给了我们一个主要/次要布局:一个主要视图充当导航,例如从我们读过的书籍列表或阿波罗任务列表中选择,以及一个次要视图作为导航更多信息,例如有关在主视图中选择的一本书或阿波罗任务的更多详细信息。

在我们简单的代码示例中,SwiftUI 将NavigationView内部的单个视图解释为此主要/次要布局中的主要视图。但是,如果我们确实提供了两个视图,那么我们会立即获得一些非常有用的行为。尝试将你的视图更改为:

当你启动该应用程序时,你再次看到的内容取决于你的设备和方向,但在 Max-sized 手机和 iPad 上,你会看到“Secondary”,而 Primary 工具栏按钮会显示“Hello, world!” 看法。

SwiftUI 自动链接主视图和辅助视图,这意味着如果你在主视图中有一个NavigationLink,它将自动在辅助视图中加载其内容:

然而,至少现在,所有这些魔法都有一些缺点,我希望在未来的 SwiftUI 更新中得到修复:

  1. 无论你是否想要,详细视图总是会得到一个导航栏,因此你需要使用navigationBarHidden(true)来隐藏它。

  2. 即使空间足够大,也无法使主视图保持可见。

  3. 默认情况下,你不能使主视图显示为横向;SwiftUI 总是选择细节。

提示:你甚至可以向 NavigationView中添加第三个视图,这样你就可以创建边栏。你会在 Notes 等应用程序中看到这些内容,你可以在其中从笔记列表向上导航以浏览笔记文件夹。因此,第一个视图中的导航链接控制第二个视图,第二个视图中的导航链接控制第三个视图——当你需要时,这是一个额外的组织级别。

将 alert() 和 sheet() 与可选项一起使用

SwiftUI 有两种创建弹窗和工作表的方法,到目前为止我们主要只使用了一种:绑定到布尔值,当布尔值变为真时显示弹窗或工作表。

第二个选项允许我们将一个可选项绑定到弹窗或工作表,我们在展示地图图钉时简单地使用了它。如果你还记得的话,关键是我们使用一个可选项Identifiable对象作为显示工作表的条件,闭包会为你提供用于该条件的非可选值,因此你可以安全地使用它。

为了证明这一点,我们可以创建一个User符合Identifiable协议的简单结构:

然后我们可以在ContentView中创建一个属性来跟踪选择了哪个用户,nil默认设置为:

现在我们可以更改ContentView中的body,使其selectedUser在点击其文本视图时设置为一个值,然后在selectedUser给定一个值时显示一个工作表:

使用这个简单的代码,每当你点击“Hello, World!” 一张写着“Taylor Swift”的表格出现了。关闭工作表后,SwiftUI 会立即设置selectedUsernil.

这可能看起来像是一个简单的功能,但它比替代方案更简单、更安全。如果我们使用 .sheet(isPresented:)修饰符重写上面的代码,它将如下所示:

这是另一个属性,另一个要在 onTapGesture()中设置的值,以及在sheet()修饰符中传递可选的额外代码——如果你能避免那些你应该避免的事情。

弹窗具有类似的功能,尽管你需要同时传递布尔值和可选值Identifiable。这使你可以在需要时显示弹窗,而且还可以从我们对工作表使用的相同可选展开行为中受益:

有了这些,你现在几乎了解了有关工作表和弹窗的所有知识,但是我想偷偷做最后一件事来完善你的知识。

你看,到目前为止,我们已经写了很多像这样的弹窗:

那个 OK 按钮之所以有效,是因为所有操作在它们被点击时都会关闭它们所属的弹窗,到目前为止我们一直在使用这种方法,因为它可以让你练习创建弹窗和按钮。

但是,我想向你展示一个简洁的快捷方式。试试这个代码:

当它运行时,你会看到一些有趣的东西:尽管没有专用的 OK 按钮,但结果与以前完全相同。SwiftUI 发现我们在弹窗中没有任何操作,因此它为我们添加了一个标题为“确定”的默认操作,并在点击时关闭弹窗。

显然,这在你需要其他按钮以及 OK 的情况下不起作用,但对于简单的弹窗来说,它是完美的。


使用组作为透明布局容器

SwiftUI 的Group视图通常用于解决 10 个子视图的限制,但它还有另一个重要的行为:它充当透明布局容器。这意味着该组实际上根本不会影响我们的布局,但仍然使我们能够根据需要添加 SwiftUI 修饰符,或者不使用@ViewBuilder返回多个视图。

例如,这个UserView有一个Group包含三个文本视图:

该组不包含任何布局信息,因此我们不知道这三个文本字段是垂直堆叠、水平堆叠还是按深度堆叠。这就是 Group的透明布局行为变得重要的地方:无论父级放置什么,UserView可以决定其文本视图的排列方式。

例如,我们可以创建一个这样的ContentView

每次点击该组时,它都会在垂直和水平布局之间翻转,你会再次看到,使用Group让我们可以立即将点击手势附加到所有内容。

你可能想知道你需要多久使用一次这样的替代布局,但答案可能会让你感到惊讶:这真的很常见!你看,这正是你在尝试编写适用于多种设备尺寸的代码时想要发生的事情——如果我们希望在水平空间受限时进行垂直布局,否则水平布局。Apple 提供了一个非常简单的解决方案,称为size classes,这是一种非常模糊的方式来告诉我们我们的视图有多少空间。

当我说“完全模糊”时,我的意思是:我们只有水平和垂直两个尺寸类别,称为“紧凑型”和“常规型”。就是这样——涵盖所有屏幕尺寸,从最大的横向 iPad Pro 到最小的纵向 iPhone。这并不意味着它没有用——远非如此!– 只是它只能让我们以最广泛的方式推理我们的用户界面。

为了演示实际的尺寸等级,我们可以创建一个视图,该视图具有一个属性来跟踪当前尺寸等级,以便我们可以在VStackHStack之间自动切换:

提示:在这种情况下,堆栈中只有一个视图并且它不接受任何参数,你可以将视图的初始化程序直接传递给 VStack缩短代码:

我知道短代码不是一切,但是当你使用这种方法进行分组视图布局时,这种技术非常简洁。

该代码运行时你看到的内容取决于你使用的设备。例如,iPhone 13 Pro 在纵向和横向上都有一个紧凑的水平尺寸类别,而 iPhone 13 Pro Max在横向上有一个常规的水平尺寸类别。

不管我们是使用大小类还是点击手势来切换我们的布局,关键是UserView并不关心——Group只是将文本视图组合在一起而根本不影响它们的布局,所以UserView布局安排完全取决于如何它的使用方式了。

使 SwiftUI 视图可搜索

iOS 可以使用修饰符向我们的视图添加一个搜索栏searchable(),我们可以将一个字符串属性绑定到它以在用户输入时过滤我们的数据。

要了解这是如何工作的,请尝试这个简单的示例:

重要提示:你需要确保你的视图在 NavigationView,否则 iOS 将无处放置搜索框。

当你运行该代码示例时,你应该会看到一个可以输入的搜索栏,你输入的任何内容都会显示在下面的视图中。

在实践中,searchable()最好与某种数据过滤一起使用。请记住,SwiftUI 会在属性更改时重新调用你的 body 属性@State,因此你可以使用计算属性来处理实际的过滤:

当你运行它时,iOS 会自动将搜索栏隐藏在列表的最顶部——你需要轻轻向下拉才能显示它,这与其他 iOS 应用程序的工作方式相匹配。iOS 不要求我们让我们的列表可搜索,但它确实对用户产生了巨大的影响!

提示:与其在这里使用contains(),不如使用另一个名称更长的方法:localizedCaseInsensitiveContains()。这让我们可以检查搜索字符串的任何部分,而不用担心大写或小写字母。


SwiftUI学习100天(Day96 - 项目 19,第一部分)的评论 (共 条)

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