保持它们的相关性和启用小部件自定义

在 iOS 14 中,我们引入了 WidgetKit。WidgetKit 允许您直接在 iOS、iPadOS 和 macOS上的用户主屏幕上创建美观、动态、多平台的小部件。

现在,在我们开始之前,如果您错过了WWDC 2020 的任何演讲,这里有一些非常棒的演讲,例如“认识 WidgetKit”,它介绍了 WidgetKit 框架及其核心概念。“小部件代码”是一个由三部分组成的系列构建小部件,从基础到高级的复杂性不断增加。“为小部件构建 SwiftUI 视图”详细介绍了如何充分利用 SwiftUI为您的小部件构建自适应视图。最后,“设计出色的小部件”通过许多示例探讨了我们人机界面组的设计注意事项。

今天我们将讨论优秀小部件的两个主题:保持它们的相关性和启用小部件自定义。因此,让我们从相关性开始。我们将深入讨论三种类型的相关性,以确保您的小部件是最新的并且可以适应其环境。我们将讨论时间、演示和位置相关性。

WidgetKit 的核心是时间线。这是 Widgets全天保持相关性的核心机制。时间线由一个或多个时间线条目组成。在此示例中,您可以看到三个这样的条目,一个在上午 9:00、上午 9:30 和上午 10:00。现在,当系统向您的小部件询问时间线时,生成的时间线将被存档,其条目将在您指定的特定时间呈现到未来。这让系统可以随时准备好您的用户界面,以便在用户需要时立即显示。让我们看一些时间线的例子,从最简单的开始,看看其中可能包含的内容类型。


截屏2021-06-22 下午5.16.15.png

这是一个最简单的时间线示例,只有一个条目:屏幕时间。现在,由于 Screen Time 无法预测或预测未来的数据,而且它严格基于用户设备使用情况的统计历史,因此它确实无法很好地利用其时间轴中的多个条目,因此它只是使用一个条目。这是您可以拥有的最简单的时间表。


截屏2021-06-22 下午5.16.53.png

尽管如此,并非所有小部件都需要是单个条目,事实上,在大多数情况下,我鼓励您考虑并质疑为什么不在时间线中提供多个条目。如果您有前瞻性的内容,有重要的日期或截止日期,或者可以将您的内容预测到未来,您的小部件应该真正利用时间线中的多个条目。这是来自 Weather 的另一个例子。如您所见,Weather 的时间线提供了多个条目,可在一天中持续数小时。现在,这里的第一个条目是最准确的,因为它代表当前天气,所有其他后续条目代表当天晚些时候的预测数据。这个额外的预测数据非常有用,因为不能保证在您指定的确切时间重新加载小部件。如果重新加载没有达到目标日期正是在需要的时候,现在系统有额外的预测内容来增强用户体验。


截屏2021-06-22 下午5.17.41.png

这是照片中的一个例子。您可以看到照片时间线提供了许多在一天中的特定时间显示的个人和相关照片。对我来说,这些都是一些非常非常美好的回忆。现在,虽然小部件每天只重新加载几次,但通过从这些多个时间线条目中呈现新的和新鲜的内容,它确实给人一种充满活力的感觉。正如您在此处看到的,即使您没有像天气这样可预测的数据(如本示例中的“照片”),您仍然可以通过利用可以使用户感到惊讶和愉悦的方式来合并与用户相关的内容您时间线中的这些多个条目。

截屏2021-06-22 下午5.18.16.png

现在,由于某些小部件的查看次数比其他小部件多,因此我们决定为小部件提供更新的公平因素。我们称之为更新预算。预算是在一天中分配和累积的,它们受用户观看习惯的影响很大。一个经常查看的小部件预计每天会收到大约 40 到 70 次后台更新,如果在用户醒着的正常时间间隔均匀,这意味着大约每 15 到 30 分钟更新一次。但是,当然并非所有重新加载都必须像这样均匀间隔,我们的目标是启用和支持针对不同要求的不同更新节奏。例如,也许您有一个体育小部件,它在最喜欢的球队即将举行的比赛之前一直处于闲置状态,然后它可以在比赛前、比赛中甚至比赛后接收大量的比分更新。

Widget reloads

WidgetKit 很智能,当用户长时间不使用设备(例如用户睡觉时)时,它可能会暂停更新。否则,在预算可用于特定小部件之前,小部件更新可能会被暂停。尽管如此,重新加载并不是每秒一次的操作。小部件不是要在主屏幕上创建实时运行体验。现在,您的小部件可以通过多种方式全天刷新。我们将简要介绍其中的每一个,以了解它们是什么、它们如何工作以及它们如何相对于我们刚刚介绍的预算发挥作用。第一个是 TimelineReloadPolicy,它是 WidgetKit 中的 API。这是自动重新加载的核心机制。当您提供时间线时,您还会在其旁边提供重新加载策略。当您想在后台自动刷新小部件时,此重新加载策略会通知系统。这些自动更新是从您的小部件当前可用预算中进行预算和扣除的。

接下来是 WidgetCenter 重新加载 API。这是一个 API,用于在发生会使您的小部件的现有数据无效的事件时刷新您的小部件。现在,通常情况下,使用此 API 的请求会消耗可用预算,这意味着在预算可用之前不会发生更新。但是,有一些特殊情况会使这些重新加载立即发生且无需预算。这些是当您的容器应用程序对用户而言处于前台或您的应用程序参与用户会话时,例如导航或正在播放的音频。

这个 API 实际上是对 TimelineReloadPolicy API自动后台更新的补充。当位置发生重大变化时,您的小部件也可以更新。当系统检测到显着的位置更改并且您的小部件使用位置时,系统将授予您无预算更新。当用户下次查看您的小部件时会发生此刷新,以便可以适当地解析位置。现在,请注意,这不能保证在位置更改发生时立即发生,而是在用户下次查看小部件时发生。稍后我们将更多地讨论位置。系统也可以刷新您的小部件,如果它的演示环境发生变化。例如,可能用户更改了可访问性首选项(如动态文本或粗体文本)、语言或区域更改、iCloud 或 App Store 帐户更改、重大时间更改等。最后,由于预算的原因,如果用户有一个很少见的小部件,它可能不会像您(开发人员)可能喜欢的那样收到尽可能多的更新。系统知道您的时间线中的日期、您的首选刷新时间以及来自用户的一般查看历史记录。如果系统认为用户查看数据时数据可能过时,则系统可能会授予无预算重新加载。当然,所有这些系统启动的更新总是没有预算的。正如我们刚才了解到的,每个时间线都配有一个重新加载策略,描述何时应该在后台自动更新。WidgetKit 在这里提供了三种选择:atEnd、afterDate 和 never。这三个重新加载策略中的哪一个适合您的小部件?让我们深入讨论每一个,并提供一些上下文示例,我们将讨论每个需要注意的问题。

TimelineReloadPolicy
  • atEnd


    截屏2021-06-22 下午5.23.27.png

    atEnd 重新加载策略。此策略将标记您的小部件有资格在时间线结束时刷新

  • afterDate


    截屏2021-06-22 下午5.28.24.png

    afterDate 最适用于可以在一天中不可预测或意外更改的内容以及准确性或相关性定期更改的数据
    如果您跨设备同步的小部件刷新。例如,美国股票市场在东海岸上午 9:30 开盘,您安排在上午 9:30 进行刷新,以从服务器获取当天的初始数据。请记住,您的小部件可能在数千甚至数百万台设备上,甚至可能在每台设备上多次使用。如果您必须像这样进行时间对齐的数据拉取,那么除了访问缓存服务器之外,您真的应该考虑向这些日期添加一定程度的随机抖动。这些是特别重要的考虑以避免任何潜在的计划外或不必要的成本。


    截屏2021-06-22 下午5.29.06.png
  • never
    never加载策略是最简单的策略,因为它从不自动重新加载。如果您的小部件的内容只能通过其容器应用程序处于前台或通过推送通知等离散事件来更改,那么永远不会是您的小部件的最佳选择。使用从never,您可以仅使用来自主app或其他附件扩展的更新


    截屏2021-06-22 下午5.31.23.png
  • WidgetCenter

  • Significant location changes

  • System updates

WidgetCenter 重新加载 API来使您的小部件保持最新。这确实最大限度地减少了仅在必要时发生的重新加载,并保持最小的影响根据您的预算和用户的电池寿命。如果您的小部件需要在您的应用程序中尚未满足的明确用户条件,那么 Never 也是合适的。例如,可能登录服务或购买某些特定内容。在您的应用满足这些类型的条件之前,如果您的小部件无法产生有意义的内容,请永远不要考虑。使用 never 策略的小部件的好例子包括 TV、Notes、Music、Podcasts、Contacts 等。这些都是需要用户在应用程序中进行交互以推动内容更改或接收这些内容更新推送的小部件和应用程序。总之,利用时间线条目对您有利。为您的小部件选择正确的重新加载策略,并使用 WidgetCenter 的重新加载 API重新加载离散事件的时间线事件。好的,让我们继续讨论演示相关性。您的小部件可能会出现在iOS 或 macOS 上的特定上下文中,这可能会导致您的小部件改变外观。有时可能会在没有任何时间线更新的情况下重新渲染小部件。出色的小部件将始终适当地适应这些演示环境。因此,我们将讨论配色方案、深色和浅色模式、部分隐私修改(iOS 15 中的新功能)以及全面隐私修改。

随着系统设置的变化,WidgetKit 将自动处理在明暗模式之间切换您的内容。这是因为我们使用了 SwiftUI 的强大功能。现在考虑您希望您的小部件在这些各自的上下文中的外观。在这里,您可以在明暗方案中看到便笺和日历的示例。但请记住,并非所有小部件都必须通过更改其背景和文本颜色来符合明暗模式。例如,有一些小部件(例如音乐和股票)不会改变其颜色。如果您的应用程序设计不知道这种深色和浅色风格的高对比度内容,然后随意继续任何对您的小部件有意义的配色方案。

您还可以通过 Xcode Previews 在 Xcode 中预览小部件的配色方案更改。这是在 Light Mode 下预览systemSmall 小部件的快速示例。

现在处于黑暗模式。我们所要做的就是添加 colorScheme环境覆盖来预览我们的小部件在此环境中的外观。如果您希望系统标准背景颜色为亮和暗模式,如下所示,然后使用 BackgroundStyle 进行填充。

小部件还受到可能对隐私敏感的演示环境的影响,例如 iOS 上的锁定屏幕。iOS 15 中的新功能,小部件现在可以在这些情况下编辑部分内容。现在,这听起来真的很令人困惑,所以让我们举一个例子来看看我在这里谈论的是什么。

让我们假设我们有一个银行小部件,我在其中显示特定帐户中的可用余额。在这种情况下,我的帐户中有 128.45 美元可用。

现在,当我们进入锁定屏幕并锁定设备时,该帐户余额仍然出现在 iOS 14 中,因为 WidgetKit 确实无法在设备被锁定时动态编辑余额信息。但是,这在 iOS 15 中发生了变化,您现在可以根据上下文标记要在这些情况下编辑的特定视图。现在,为了向您展示如何做到这一点,我们所做的只是在表示余额金额的文本上插入.privacySensitive 视图修饰符。因此,当未锁定密码时,如您在此处所见,该视图仍会按照您的预期呈现余额金额。但是当我们现在锁定设备时余额金额被屏蔽或编辑。


截屏2021-06-22 下午8.36.20.png

此属性可以应用于任何视图,包括hstacks 和 vstacks 等容器视图。如果应用于容器,整个容器将被编辑。

当设备被密码锁定以完全编辑内容时,WidgetKit 可以自动用您的占位符内容替换您的活动时间线内容。它甚至可以在设备被密码锁定期间暂停更新。当您采用此处列出的默认数据保护权利时,这一切都是可能的。您的时间线数据将根据您的意愿存储在设备上的该数据类中,非常重视您的数据隐私。

最后,我想谈谈位置相关性。小部件,如您的应用程序,也可以提供我们当前物理位置的上下文信息或者只是以一种或另一种方式与用户相关的位置。

如果您的应用程序正常使用位置,那么您的小部件很可能也应该使用。因为小部件可以在主屏幕和Mac 上的通知中心有多个实例,除了使用当前位置之外,还可以考虑为您的小部件提供预选甚至可搜索的位置,就像我们通过 Intent 的力量处理天气小部件一样. 现在,要在您的小部件中获取当前位置,只需要几个步骤。首先,您需要在 Info.plist 中指定NSWidgetUsesLocation 键。这让系统知道您将使用来自小部件扩展程序的位置。其次,像往常一样使用 CLLocationManager ,除了这次来自小部件扩展中的 TimelineProvider。考虑您的小部件所需的分辨率,因为定位大概位置的速度更快,如果您不需要超精确的位置,它可以带来更好的用户体验。一般来说,请求的位置越精确,解析所需的时间就越长。

最后,您可以使用CLLocationManager 上的isAuthorizedForWidgetUpdates API检查小部件是否被授权进行位置更新。这将告诉您用户是否已授予您的小部件使用位置的权限。说到权限,让我们更详细地看看小部件的位置权限,看看它们是如何工作的。小部件的权限通常与其应用程序容器共享。在这里,您可以看到“设置”应用程序中可用的可用位置权限列表。

如果用户选择“While using app” ,则仅当小部件的容器应用对用户而言处于前台或其他认为该应用正在使用的情况下(例如处于导航会话中)时,小部件才可以使用用户的位置。

如果用户选择“使用应用程序或小部件时”,则位置可用与“使用应用程序时”相同,但具有特定于小部件的额外许可。这允许小部件权限在最后一次查看小部件后最多 15 分钟接收位置。如果使用这两个权限集中的任何一个都无法解析位置,请考虑替代内容,甚至可能是先前的内容(如果可用),或者只是表明无法解析位置。如果用户为权限选择“始终”,则小部件将始终具有访问位置的可用权限。

最后,让我们谈谈构建可定制的小部件。我们将讨论大小、种类和配置作为用户个性化其小部件体验的一种方式。现在,小部件有各种不同的尺寸。并且建议支持尽可能多的尺寸,以便用户在放置小部件时有选择。请记住,设备之间的大小确实存在小的差异,最好尽可能使用系统标准的填充、边距、文本样式和文本大小。

iOS 15 中专门为 iPad添加了一个新尺寸,超大尺寸。

在这里,您可以更好地看到它。它与大型小部件的高度相同,但更宽以展示 iPad 上可用的更多内容。这是将它添加到小部件的方法。在这里,我已将其添加到已支持 systemLarge 系列的现有小部件配置中。


截屏2021-06-22 下午5.39.14.png

个性化的下一个轴是小部件类型。各种小部件为您的数据或内容提供了不同的视角。所以想一想在你的应用程序中什么样的小部件可能最有意义。描述这些的最好方法实际上是通过示例。这是时钟的一个例子。在左侧,我们有一个城市小部件,用于跟踪单个城市的时间,在右侧,一个世界时钟小部件可以在同一视图中容纳许多不同的城市。这是股票的另一个例子。在左边,有一个股票符号小部件,显示给定股票的股票价格——在这种情况下,苹果——右侧是概览小部件。概览小部件将显示反映在用户股票应用程序中的一系列股票。那么如何发布这些不同类型的小部件呢?好吧,发布多种小部件非常简单。

使用之前的股票示例,这里我在左上角有一个符号小部件和一个概览小部件。要发布这些,您只需在 WidgetBundle 对象中返回不同的小部件配置,并将 @main 属性包含到 WidgetBundle 中。就这么简单。请注意,小部件在包中定义的顺序也非常重要。此顺序反映了您的小部件在小部件库中的显示方式。因此,请确保列出的第一个小部件是您的英雄用例。最后,一旦您的应用程序被安装,就不可能动态发布或动态收回小部件的可用性。因此,随着时间的推移,应该对小部件的支持应用一些注意和思考。

可定制性的最后一个轴是通过配置。小部件支持两种类型:静态和基于意图的配置。静态小部件配置为每个小部件实例提供相同的内容。还记得之前的股票概览示例吗?好吧,即使它们位于用户设备上的不同位置,每个人也会显示完全相同的内容。静态小部件非常简单,它们是优雅的小部件定义,因为它们不需要用户的配置或设置。

另一方面,意图小部件配置为每个实例提供用户配置的内容。查看右侧的这些股票代码小部件。该用户配置了许多不同的实例,每个实例展示不同的股票。现在,这是一些非常甜蜜的东西。用户甚至可以将所有这些组合到主屏幕上的一堆小部件中,以便翻阅以节省空间。

那么这些是如何由用户配置的,您可能会问。好吧,从用户的角度来看,系统将提供所有周围的 UI 部分。在支持 Intent 的编辑模式下点击小部件后,将显示配置盘。它提供了用户可以配置的 Intent 参数列表。在这个例子中,Symbol有一个要跟踪的参数,它的值当前是 Apple 股票的字符串 AAPL。现在,一旦用户点击一个参数,就会出现一个输入控制器来收集用户的输入。完成后,小部件将自动更新。现在,您可以使用 Intent进行大量自定义,如果您需要 Intent 配置,我将稍后分享 WWDC 2020的精彩演讲,以帮助您入门。与此同时,让我们快速强调一下基于 Intent编写小部件与静态配置之间的区别。

静态配置非常简单。您只需使用标准 TimelineProvider实例化一个 StaticConfiguration 对象。让我们将其与 Intent 配置进行对比。唯一不同的是,StaticConfiguration被 IntentConfiguration 替换,而 TimelineProvider 被IntentTimelineProvider替换。每一个都有一个稍微修改的界面来支持 Intent,这样你就可以在填充时间线时接收用户配置的 Intent。有关为小部件创建和配置Intent的更详细信息,包括对支持的各种数据类型的概述以及它们在配置 UI 中的样子,请查看WWDC 2020 的“为小部件添加配置和智能”演讲。

最后,我们回顾了优秀的小部件如何利用它们的时间线条目、掌握它们的重新加载策略以及适应它们的演示和潜在的物理环境。计划提供不同的尺寸、种类和配置,为您的用户提供动态和个性化的体验。谢谢你。

你可能感兴趣的:(保持它们的相关性和启用小部件自定义)