大多数浏览器和
Developer App 均支持流媒体播放。
-
iPad 上多窗口功能简介
多任务处理是一种绝佳方式,能让您的 iPad app 变得更强大。它可以让您的 app 轻松并排运行两个界面,您的客户一定会爱上这项功能。了解如何利用拖放等现有功能,以及如何使用它们来轻松创建第二个窗口。了解多窗口支持如何改变 app 生命周期,以及它对所有 app 的意义。了解一些常见的错误及其解决方法,为您和客户打造超凡体验。
资源
相关视频
WWDC21
WWDC19
-
下载
(iPad多窗口介绍) 谢谢 下午好 我是Ken Ferry 我来自iOS System UI团队 就是你们可能听过的Springboard 今天 我同Steve Holt 和James Savage 一起来介绍一下iPad的多窗口
我们来聊下什么呢? 在iOS 12以及之前的版本 如果你上滑切换器 你会看到一些小巧的格子 点击其中一个 你就能跳转到相应的app 很棒吧
在iOS 13… 也是类似的 但你看到的不再是app了 它们由窗口取代了… 如你所见 它被称为API窗口
这就是我们今天要聊的内容 来讲一下它能为你的app带来什么 因为今天只是介绍 所以我只简单概述一下 我们先从设计问题讲起 你可能会想多窗口 在你的app有什么用? 我们来从app的生命周期为入口 来聊一下多窗口视图是怎样对 app编程模型 做出了重大的改变的 我会介绍如何制作窗口
从那里讲起 到拖拽 这是你们大多数人制作窗口的方法 为了让你的app具有多窗口功能 接下来 James会说明 你想知道或需要 在你的app里适配的下一个步骤
那么我们开始吧 我们来聊一下设计问题 以及… 首先 我们来讲一下 什么是窗口或视图
这其实是两个问题 第一 我的app 可以支持多窗口吗? 如果可以 接下来… 那窗口是什么样子的呢? 它们是怎么工作的
用户能习惯它们吗?
我们会用Apple内置的 app来回答这些问题 以及告诉你如何在你的app中实现 那可能是你想知道的
我们来看一下Safari Safari是多任务app的 一个范例 如图所示
这是iOS 12上 Safari的一个截图 它已经支持了分屏视图 在iOS 13上 它是这个样子 在iPadOS 它是这样的 并没有太大的区别 它是如此重要 甚至当我们还不能 在整个操作系统上实现时 我们在Safari上先实现了
总体来说 我们要了解的
第一件事是 在Safari上窗口类型只有一种 每个窗口都是一样的 它们在界面上相互克隆对方 每个窗口都包含app的所有功能 这在iPad上很重要 因为 用户需要能够在每个窗口使用 所有的功能 当用户觉得有多窗口的必要时 它们也能够创建 如果你的app需要多个窗口 才能完成某件事时 那是一定有问题 虽然你不一定要确保 每个窗口都一模一样 但是你要让第一个用户创建的 第一窗口具备所有功能
所以 如上所述 它们都是一样的 在大多数Apple的app中 你会发现我们是这样做的 那不是一件坏事 对你来说 它既是容易 也是对的事情 我们来看个例子 在我开始之前 需要说明的是 因为我们对此采用了 系统支持 在Safari中的操作更棒了 现在你可以拖动一个窗口到一边 只专注于一个窗口的内容 很酷
下面我们来看文档类型的app
现在 我们看到的是Pages 用户在使用任何文档类型的app时 都有想要同时 查看多个窗口的需求 所以你一定要支持多窗口
这里 你可能会 觉得有点惊讶 如果你看这些窗口的左上角 都有一个“文档”按钮
每个窗口都其实相当于 一个浏览器窗口 你可以返回到上一个文档 查看另一个 其实是和Safari一样的 只有一种类型的窗口页面和文档页面
在每个文档里都不是必须的 我觉得并不是每个文档相关的app 都要强制 但在这里 其实是有用的 但我们接下来看到的例子不是这样的
Maps也是 只有一种类型窗口 这里我提及它的理由是 因为它表明了我需要让我的app 支持多窗口的其他理由 首先 这并不是一个典型的例子 因为它就像 你打开Maps 查找了一些信息 然后关掉它 它就是这样工作的
但不是这样的 假如你在计划晚上的活动 你可能会先去吃晚饭 然后去看一场演出表演 如果两件事能在不同的窗口做 岂不是很好 你能在不干扰相互两件事的状态 的同时思考或改变它们
那似乎是针对于Maps的 但我们要实现多窗口的原因 是因为我们在很多场合都需要这么做 所以 我们并不能保证在所有情况下 有用与否 但我们保证多数场合是需要的 所以 我们会用更多的例子来说明 但你也要想想自己的app使用场景
你知道的 因为使用系统的多窗口设计时 当你想要选中它们中的一个 比如我想要去晚餐地点 我能重新安排我的空间 打开Notes 我能比只在一个app里
做到更多的事情
Mail是我们将要看到的 第一个使用 不同类型的窗口的app
Craig在Keynote演讲 演示过 但当你回复一则信息时 如同往常一样 模态框出现了 但你可以把它挪到一边 接下来 你甚至可能想要使用 像待办清单一样的 待办层级列表
所以这种情况下
请再看一下窗口上方 有一个蓝色箭头的“发送”按钮 还有一个“取消”按钮 但你无法在此处返回上一级 来查看你的邮箱里的其他内容 这是窗口的特殊设计
接下来 当你
点击其中任意按钮 你就能关闭窗口 我觉得Craig已经在 Keynote演讲展示过发送方法 所以我来展示一下退出的效果 如果你想退出右侧视图 只想查看他们其中的一个 接着点击“取消” 它看起来是这样 你也能在自己的app中 实现这些动画效果 我会在随后的会议中讨论
Messages 也有不同类型的窗口 但不是像待办清单窗口的那种 它并不像是一种事务或 其他案例操作那样 这里 当你单独为一个对话 打开一个窗口 这只属于这个对话 的特定窗口 当你想要关闭时 你能在最上方看到“完成”按钮
这更像是一个管理工具
但是非常好用
接下来 我们回到为什么我的app 需要支持多窗口的视图的问题 在Messages里 我发现在和某个人在一个窗口聊天时 如果我能查看另外一个聊天记录 并引用其中的聊天内容 发送给我正在聊天的人 是非常高效的体验 当我和别人聊天时 如果他们有更多的问题 我不必退出当前聊天的界面 找到其他的聊天记录再回来告知他们 我一直都在同个窗口 所以 我觉得可以概括为 能够简化处理多项事情 当你在一个窗口处理一件事的时候 能同时查看其他内容
最后一个示例Apple app 是Calendar
有趣的是Calendar已经支持 拖拽事件了
但为它适配多窗口之后 你可以在Calendar 同时看到不同的两周 你可以把任务从一周拖到另外一周 在Calendar里并不需要 其他操作就能完成 这就是它已有的拖拽功能 所以如果你的app支持拖拽功能
和多窗口视图 你也能拥有这种两种功能 一并工作的超能力
所以 就像我说的 非常厉害 具有这个功能的app 都能做很多有用高效的事情 虽然我不能为所有app 回答这个问题 你可以自己想一想 但这些示例也许 能概括一些你的用户的使用场景
在开始下一个话题之前 我还想再提一点 我们今年对比过Mac和iPad 上app的不同设计 Mac的app都有窗口 如果没有这个API 你就不可能创建新的窗口 这是一类怪异的Mac app 但现在你能做到了 我们来看一下 (创建窗口应该如何设计交互?) 我们已经讲过了窗口 现在 我们还是以设计的视角来看看 你可以在你的app使用怎样的交互 来让用户创建新的窗口
我们首先来看看系统提供了 哪些功能 然后根据已有的功能 想一下用户的使用场景 对于初次使用app的用户 Craig已经展示过 App Expose了
在App Expose里 右上角一直都有一个小按钮 那个小按钮就是用来创建新窗口的 这就是系统提供的一个功能 如果你想要为你的app支持多窗口 这样你就能创建了
还有另外一个所有app都可以 实现的方案 但这是一切的基础 如果你已经打开你的app 然后拖拽这个app的图标 到屏幕边缘
这很明显是在说 我想要在这里创建一个新的窗口 还有其他意思吗?
现在我们已经拥有可以实现 这个功能的所有内容了 那就开动吧 但有个问题 现在 当一个用户选择了其他选项 比如Safari中的一个标签页 他们拖拽这个标签页到一边 独立成为另一个窗口视图 他们觉得这样也行 但系统并不能自动实现 不过通过API来配置并不会很繁琐 但是你要自己来实现这个功能 所有拖拽动作都能延伸出这个功能 只要用户能取出一个组件 它就能形成一个任意类型的新窗口
用户会觉得这样做是可行的 所以你要支持这个功能
一种常见的使用场景是使用 主细节视图类型 在Mail app里面
左边有个表单视图 里面的每个单元格都表示一则消息 只要一点击每个单元格 就能看到消息的所有内容 没错吧? 所以当把单元格拖出表单视图时 用户想要看到的是 有一个新窗口来展示这则消息
这就是拖拽的全部讲解了 (用户直接创建行为)
你也可以直接创建新窗口 比如在Safari 或有链接的app 你可能想要支持 按住一个链接 就有一个提示框弹出 提示框里有个按钮 “在新窗口中打开” 这是在Safari里面的效果 你也能做到 如字面意思一样 说在新窗口打开
所以在UIKit的API里面 只要你调用它 它就能打开一个新窗口
你可以用它来做很多事情 比如创建一个声音识别的功能 当我打喷嚏的时候 它就会创建一个新的喷嚏窗口 来分析我的喷嚏 就像Shazam或其他类似的
你也能做到 但会有点奇怪
所以你最好不要那么做 这听上去很有趣 但你知道的
就像我们之前说的那样 用户不应该被强制使用多窗口功能 他们应该自己选择创建与否 所以当用户有创建的新窗口 的需要时 你就需要提供比如 “在新窗口中打开”的功能 但是这只是设计层面的构想 所以你需要在你自己的app里实现 这个功能
关于设计 我们今天 就聊到这里 接下来我们来讲一下如何实现 有请Steve Holt
(UIScene生命周期的实现)
谢谢大家
谢谢Ken 我是Steve Holt 我是UIKit团队的一名工程师 你今天幸运地看到了 如何将这个新功能引入到app中的 一些优秀的示例 你可能在想 你是如何在app中实现的?
我们现在就来了解一下
总体上来说 为了在iOS和iPadOS 实现这个功能 你需要了解两个类 (UIWindowScen和 SceneSession概述) 就是UIWindowScene 和SceneSession
现在 你可能很熟悉UIKit里 UI的结构组成 你有一个屏幕 你有所有的窗口或多个窗口 取决于你的app 接着 你的视图以及视图控制器 都在窗口里面
UIWindowScene介于 屏幕和窗口之间
你可以将你的窗口 作为用户界面里的一个实例 而无需从现有基础上 强制改变你当前app 和用户界面太多
简单来说 一个视图 包含了用户界面 当你需要时 你可以向系统索取 在你的用户界面 当用户使用拖拽 或其他方式 请求打开一个新窗口时 系统会问你是否想要将UI 放在屏幕上
接下来 如果这个窗口应该返回至后台 不需要有交互的必要时
系统就会判断它是否 只需要悬挂在那儿 我们不再需要它了 我们可以销毁这个窗口了
当我们销毁这个场景时
用户还是觉得那里有什么 你的app还在转换器右侧 之前的位置
你需要 不依靠某个特定的用户界面
就能懂得转换器 在你的app被悬挂时里面有什么
这是SceneSession 所处的位置 (从会话中连接和断开视图) SceneSession表示用户 在app的最后操作的用户界面状态
现在 他们定义了一个系统角色 这可能是一个标准的app用户界面 你可能是在真实的设备上运作 或是外部的连接设备
每次 当一个新的窗口在系统上创建时 你的app被app代理告知 有一则新会话被创建了 只要用户通过我们的API的交互 或向上滑动销毁空间 销毁了其中一个 你就会收到会话被摧毁的通知
你的app的生命周期中的 UI窗口从先前的侧栏 连接和断开
现在 你app的生命周期中有 你可能感兴趣的有趣的现象
我们用一个图标来分析一下
在这个app中 我的app的用户界面 有3则会话 分别代表了3个不同的系统空间
现在 它们是断开的状态 它们都低于后台线 所以 我的app的状态处于后台
现在 如果你想激活其中的一个空间
app被连接的那个 窗口状态线上升了 上升到了前台活跃状态
当我把窗口送回后台
对应窗口的状态下降了
如果我切换至其他两个会话 我的app就会保持 前台活跃状态 来说明我的app的整体状态 没有改变
至于你app的类 和你app的委托类
我们习惯将用户界面、系统、 ApplicationDelegate 生命周期 和app对象结合在一起 这样的运作方式不在那么适用了
所以 我们把它分开
你的app仍然代表系统的状态 作为一个系统过程 ApplicationDelegate 获取事件 委派关于进程、事物等消息 以及打开和终止app的进程 但现在 你的窗口已经包括了 UI全部的状态 有关于状态栏的问题吗 你问现在的窗口
接着你的 SceneDelegate收到消息 在一个特殊的上下文中打开链接
离开后台 回到前台 等等 当然 SceneSession 会表示持续的UI状态
现在 你可能觉得 有太多复杂的API了
如果你的app现在有如下代码 你要做出很大改变了 你要将你的实现方法
转变成这些方法
对于其他大多数内容 我们尽可能保持和之前一致
app在启动时 会话是willConnectTo
EnterForeground 代表进入前台状态 它只是在窗口上而不是app里 等等
这里 有个状态重置的小问题 它非常重要 你的用户能查看转换器的状态 进入一个特殊的空间 得到他们想要的信息之后离开
为了协助你完成
我们从Handoff那里 借用了一些API
我们现在将stateRestoration 作为一个NSUserActivity
你可以放入任何你想要的信息
在生命周期的许多节点上 它会从SceneDelegate 请求用户活动信息
接着 当你的窗口复原时 会马上将它传给连接代理的回调函数
这时 这个特殊的会话将 不会有任何窗口存在 你能直接在会话中 获取 stateRestorationActivity 这样你就能从后台状态恢复过来 需要更新一个新的窗口 你能找到你想要改变数据的那个
我们来看一个快速演示 (演示 实现多窗口支持) 来看一下 在你的app接入新的API 之后是什么样子
那么…
我这里有个我好朋友 我们组的同事John Ham 授权的app 他的这个app 是我的最爱之一 几秒钟之后 模拟器出来就能看到了 它真的很酷
它启动之后 你将会看到 这是一个很酷的相册集app 运用了集合视图和流式布局
但我会用它来讲很重要的一点 它真的很赞 接下来
我们会从一个它的一个实例入手 来讲多窗口的实现
因为当我使用这个app时 我很想要
能够同时查看多张图片
我们再等一小会儿 等模拟器加载完成 好了
我们启动app
你看 这是一个超棒的app 我能进入查看所有的照片 然后返回
现在… 我打开它 试着进入App Expose 但在这里不行 这是因为这个app没有多窗口视图
所以 实现的第一步
先进入Xcode
在General标签这里
找到这个新的复选框 标签Supports多窗口
你猜一下我点这里会发生什么
我们刚才略微改动了一下 我们的info.plist文件
如果我们进到里面
这里多了新的一栏 app视图清单 它将告知系统
这个app支持新的生命周期界面 我们静态申明了 我们想要使用的一类用户界面 现在 我提前为你打包了 一个info.plist入口 所以我们不用它
现在我们使用
这个
我们完成了 它已经在我们 已有的Storyboard上了 我们有一个非常基本的 SceneDelegate类 在这里 所有的这些都是在声明 一个窗口 它是非常基础的类
我们构建一下 让它跑起来
和刚开始展示的一样 很好
不过现在
我来看一下是否 可以使用程序坞的图标 我向上拖动它 移动它到iPad用户界面的边缘 创建一个新的窗口 就是info.plist 允许我们操作的
不过 不幸的是 如果我们返回到主界面
这个app终止运行了 接着再启动它
它并没有返回到正常的状态 你看这里才是
为了修复这个问题
我们需要做一些事情 是可以做到的
现在 为了在这里实现 stateRestoration 我们需要恢复我们已有的 stateRestorationActivity
窗口会给视图从新的 stateRestorationActivity返回它 委托回调
我们进一步看一下实现方法 我们在app的实例中设置过它 这并不是我们想要的了
我们设置它为本地的 窗口视图
接着 在窗口消失之前清除状态
现在 我们返回了用户的活动状态 所以我们能实现stateRestoration
来试一下
你看这里 我们并没有完全实现 stateRestoration方法
在我们窗口连接前我们还需做一件事
当窗口连接到 SceneSession 我们得到了选项 和会话参考 现在 在我使用的这个模版里 我们已经通过在Handoff 和其他系统设置 那寻找用户的活动
我们想要得到这些用户活动 因为这是用户实际操作的
不过…
stateRestorationActivity 很特别 而且它在会话里面 所以当你的活动不存在时 我们会使用 stateRestorationActivity
现在 我们建立并运行时
我们修复了 当app再次启动时的问题
所以 这就是如何在你的app中 实现多窗口的功能 非常简单 你能使用你app中大多数原有的 app代理逻辑 将它移动到窗口场景 就可以了
现在 Ken提到过的 (APP生命周期的变动) 拖拽物件最好的交互方法 是使用拖拽功能
以及其他几种方法实现 如果你使用 你在info.plist
声明的通用链接 或文件目录的路径 这是有效的 但如果你想做一些更客制化的事情
你也可以使用 NSUserActivity 你可以在你已有的DragItem 的NSItemProvider以不同的对象 加入它
就像拖动其他任意的app图标 当你从系统中拖动它时 你能得到点击物件和 系统定位的拖动点
下面有请我的同事James 讲解下面的步骤 (下个步骤)
谢谢
谢谢Steve
总结一下这次演讲 我还要讲三件事 第一件是更深入了解 UISceneSession API (完善APP的下个步骤) 接下来 我们来学习一些 当你复制你app的用户界面时 你可能见过的常见问题的一些用例 最后 我会简短讨论一下我们为 app添加UI支持 新的生命周期的一些反例
所以我们来以 什么是视图会话开始
回到我们早些时候的示意图 在App Switcher里 我们有4个app的窗口 用户会这么想 四个窗口 但我鼓励你以开发人员的角度 来想一下这些视图以及视图会话
该区别很重要 因为 用户在App Switcher看到的窗口 一直都是缩略图 这些视图不会在你的app中加载
它们按需出现和消失 但是会话一直都是可用的 因为这样的设计 我们使用会话 来有规划地控制窗口
今年 我们出了一些可以用于 多任务处理的API 因为它们允许你以代码的方式 来创建新窗口 在App Switcher 更新缩略图 或着当它们展现的文档过期时 使用手势关闭它们
来看一下你应该如何使用它们 我们来看一些示例代码
第一个是 requestSceneSessionActivation API 它能让你将app中 已有或新的窗口移到前台 这个例子中 我会打开一个文档 我先检查这个文档是否 在我的app里已有了窗口 如果有 我将它传给这个API 它就会被带到前台 但如果这个文档还没被打开过 我可以根据上下文创建一个 NSUserActivity 我等下要打开它 传nil给它 创建一个新的窗口
下一个是 requestSceneSessionRefresh API 当一个事件改变了 你会在你想要收到 一则推送通知的场合中 或是Calendar app中 使用这个API 当你调用这个方法时 UIKit将会在未来某些节点 安排更新 它会在后台连接到你的窗口 你就能有机会改变UI 生成一个新的缩略图 它之后会被保存至 App Switcher 你能使用它来更新 stateRestoration用户活动 Steve已经说明过了
最后是 requestSceneSessionDestruction API 你可以使用它来关闭一个视图 最酷的地方在于它和 视图…这个选项对象 一同出现 你可以为窗口关闭时 选择一个语言动画效果
你能在Mail的相关窗口看到 当用户发送了一则消息 这则消息向上跳出了屏幕 当用户保存它为草稿时 它会向下滑动提醒用户已被保存
你可以在你自己的视图和app中 使用类似的动画效果
现在 窗口管理并不是 会话唯一能做的事 我们同时也为它加入了 状态修改功能 在NSUserActivity里的 stateRestoration就是这样
我们为考虑过许多app 这是保存状态的最简单的方式 特别是你已经使用了类似 Handoff的技术
我们也同时发现很多app 已有的状态修复逻辑 你可能并不想用 NSUserActivity来集成 针对这种情况 我们有一个 persistentIdentifier属性
现在 所有的这些 是一个已由系统集成的字符串 你能很简单地在你的数据库加入它 或在你app中 其他的文件状态变动时 它会成为相同视图的标识符 每次当你的app启动时 甚至是备份和设备里的 恢复文件
最后 这里有一个 userInfo目录 用来存储小体积的数据 比如每个视图的自定义设置 当一个侧边栏出现时 或颜色选择器中最后选择的颜色 你可能想要使用它 从这里查找东西很棒 你能找到你在用户默认设置值 因为这些值你可能并不想要 将它们暴露给 你整个app
所以 这些就是 UISceneSession新的API 下面我要讲的是 当你使用Xcode 支持了多窗口视图 构建并运行app之后 你下一步要做什么 当然是调试排除故障了 (排除故障技巧) 现在… 你app中的很多代码都非常 客制化 我们尽了最大的努力设计了框架 来帮你 不过 我们不能预测 你需要修改的地方 和内容
但我们列举了一些 我们希望你能思考一下 你过去写过的代码 适配这个新的生命周期 特别是实现多窗口的功能 可能改变了你的 之前你构建app的想法
现在不止一个用户界面了 也许不再只有一个 视图控制器的实例了 (每个APP都有它自身的挑战 除了改变无其他选择) (测试 测试 测试 更多测试) 当然 如果你能自动化测试 那是最好不过了 虽然有些错误测试未必能测出来 甚至是你的用户也不能 因为你对自己app的 整体构建的改变 所以在你的用户发现问题之前 最好的测试方法就是 玩你的app 你一次可以复刻两份 这是一个检测错误的好方法 你能马上看到一些 违背你设想的错误
现在 我准备了几个案例 来重点讲一下你看到的经典错误 (关注多窗口视图) 这两者的都有特定的主题 主题就是状态 特别是分享状态
现在 我猜你们一定 在app中使用过其中的一个类 因为它们很常见 在Cocoa类中很有用
因为单例的属性 它们使用起来非常便利 你能在你的app中使用模型对象 获取到UI设备的单例 读取一些你正在运行的设备的配置 这非常有用 但这个方案也能解决问题 因为它松散的连接着视图层和数据 你可能会丢失你app中流动的一些 正在被访问的数据
但像我说的那样 它们是非常有用的模仿示例 因为它们真的很便利 事实上 我希望你们能自己 依据情况写一些单例 你可能使用一些并不典型的单例 比如 一个全局变量 或是配套元件上附带的一个单例 或是你使用的文件系统 它本身就是你app分享的 一个数据集
这里 我并不是要告诉你如何摆脱 你所有的单例 或分享状态是不好的 但我鼓励你思考你如何分享它 或着你是否该分享它 将你的数据分享出来有很多其他优势 比如在单元测试中更省时
下面我们进入到案例学习中 第一个是状态修复 (案例学习 状态修复) 我想在介绍之前 先展示一下这个示例app 这是一个小型的便签编辑器 你可以在里面输入一些文字 当你退出重启后 内容不会消失 我遵循了这个演示的几个步骤 来支持多窗口视图 效果很好 但当我退出并重启app时 我app的两个窗口的内容 都变成一模一样了 这不是我想要的
所以我看了一下我的数据集 问题非常简单 我将这个文字文件保存在 我的app容器里面 但我的路径只有一个 所以我app的每个窗口保存的文件 都被对方重写了 现在 UIKit并不能 直接拿来就用 因为这是我自己app的代码 所以我要完成两件事 我需要为正确的窗口 和会话视图关联持续存在的识别器 接着更新我的逻辑 这样我就能保存多份文件了 而不是只有一份
现在如果你保持这种惯例 来做状态修复 还有一件我想说的是 清除数据
当UIKit为你管理 NSUserActivity时 当你移除它时 它会留意去哪里写入它 不过当你接受到大文件 和你的app的生命周期绑在一起时 你接下来会想使用 新的UI app来清除它们 didDiscardSceneSessions API
它被称为 sceneSessions的集合 它是用来移除 多余数据的好工具 一个文档类型的app 比如Pages 你不会想要删除 文件系统里的文档 但是配置和偏好是不需要的
在你的app窗口中 你的app正在运行 当用户向上滑动 App Switcher 这个方法会被立刻调用 否则 在你下一次启动时 你将会收到多个窗口视图
(案例学习 用户默认配置) 下一个用户案例 我们来看一下 UserDefaults 是app中 另一个非常常见的类
UserDefaults 被用于管理设置 这就是我在这里展示的原因
在我app里 有这个字数统计的切换键 当我打开它 在屏幕底端会出现字数统计
但不幸的是 当我的设置视图控制器出现时 它才会出现 它没有在所有窗口出现 这不符合我的预期 我想要它成为我app的全局变量
当我想它是如何发生的时候 问题同样变得非常简单 我有一个设置视图控制器 和它的代理
只要设置有变化 我告诉代理 就是文字编辑视图控制器后面的 更新了UI 这是一个非常独立的进程 我app的第二个窗口 不会接收到改动的消息
有几种结局方法 最优雅的方法是键值监听
两部可以实现
第一步是通过一个扩展定义一个 UserDefaults属性 我能得到一个键的路径 用来实现键值对的监听 这是我的isInfoButton 不是 是isInforBarHidden 的布尔属性 我利用已有的get和set方法 来实现 UserDefaults
接下来 我回到我注册过监听 UserDefaults的 视图控制器 它使用了我在扩展中 定义的键的路径 只要当值改变时 改变处理器就会开始工作
重要的是我也向这个注册器 传了选项的初始值 这非常酷 只要我创建它 它就开始调用改变处理器 这意味着我无需再重复这段代码 当我的视图加载完成后 以及收到了这个更新 我无需调用这个方法 关于展示的正确与否 只有一条真理/b> 这是确保你app的界面 是否连贯的好方法
现在 一切都很完美
希望我们能给予你 一些app上面的灵感
如果你的app已经做得很好了 你也许已经使用了这些方法 你无需改变
说到最佳实践 我想要聊一下UIApplication 的一些不好的使用习惯
Steve提到过 我们给用户界面状态划分了不同职责 通过UIApplicationDelegateand 来处理生命周期
我们也划分了 UIApplication
现在你能在app中拥有多个窗口 同时可见 其中一个能使用浅色状态内容 其中一个能使用深色状态内容 只返回一个结果 对我们来说不合理 因此 我们不建议在UIApplication 使用此类属性 窗口视图有一些新的可以尝试
我们鼓励你使用这些新的属性 甚至是今年没有打算 为你的app支持多窗口功能 因为它会引导你进入正确的构思 如果你以后再试用的话
我们今天讲了很多 所以我来简短做个总结
最开始 Ken带大家使用了 我们今年加入的很多强大 的新功能 重新构思了ApP (总结 多任务处理的新功能合集) 我觉得用户真的会想要 使用这些app 因为它们有用且方便 (用户会期待这些交互行为) 因此我鼓励你采用它们 (在已有或新APP中简单集成) 我们创建这个API来让 已有的app更轻松地进行适配 我们为新的app推荐的最佳实践 事实上 它将成为 Xcode新项目的默认模版 使用UI视图生命周期 (多数问题的解决办法很简单) 我也想鼓励你 因为当你在为新的生命周期做适配时 会遇到一些问题 问题的解决方案可能很简单 包括在之前的WWDC 我们谈论过的 (使用UIWindownScene来代替 UIApplication方法) 最后 我想鼓励你们移除 现在已不太适用的UIApplication 属性 用UIWindowScene来替换 当你升级到iOS 13时 或升级iPadOS时 所有这些都可使用 你不必因为多窗口的优势而一定 采用这种设计
这周我们还有几次 关于多任务处理进阶的演讲 以及这周的一些实验室活动 包括了周四的多任务处理的内容 (更多信息请访问 DEVELOPER.APPLE.COM/WWDC19/212) 谢谢大家今天的聆听 祝大家度过愉快的一周
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。