大多数浏览器和
Developer App 均支持流媒体播放。
-
认识附近交互
附近交互框架是在包含 U1 芯片的选择加入的 Apple 设备之间查找距离和方向。探索这种强大的硬件和软件组合能够使您基于两个或多个设备的相对位置创建直观的空间交互。我们将向您介绍此基于会话的 API,并向您展示如何提供全新的交互式体验,所有内容都已经考虑到隐私。
资源
相关视频
WWDC22
WWDC21
WWDC20
-
下载
(你好)
你好 欢迎来到 WWDC
大家好 欢迎观看“认识近距离交互”的讲座 我叫 Yagil 是 Apple 定位团队的一位工程师 今天我们会讨论如何在 iOS 中 构建一种基于空间感知的 全新用户交互类型 从本质上说 空间感知 是指了解你周围的实体世界
你手中的设备所具备的这种了解 能够转而与外界环境进行流畅交互
这是 iOS 13 中的隔空投送 顶端我突出显示的选项 使用了在 iPhone 11 上 首次可用的空间感测技术 用户可以将他们的设备朝向其他人的设备 来对共享键做出明确提示 以显示最恰当的共享选项
这种高保真的交互 多亏有 Apple 设计的 U1 芯片才能实现
我们希望大家 在自己的应用软件中得以使用这项功能 所以今天我们要引入“近距离交互框架” 它是 iOS 中 一个强大却易于使用的空间感知接口 我们首先来说说用户控制和透明度 比如说你的 app 想与另一位用户的设备 运行一个近距离交互会话 那么系统会做的第一件事 是在双方的界面都出现一个权限提示 (“MySpatialApp” 想要发现附近设备并被发现) 用户可以选择不允许你的 app 与附近的设备进行交互 也可以只允许一次交互 并在退出 app 后失效 (不允许 允许一次) 如果两边的用户都授予了权限 他们的设备 就可以开始获取他们之间的距离 以及相对方向 (距离 5.3 米)
如此完善的空间信息能够让你为应用软件 创建更加自然直观的用户体验 近距离交互可以在装配了 U1 并运行 iOS 14 的设备上使用
今天我们会介绍以下内容 我会讨论 iOS 中的空间感知 在近距离交互上的使用 接着我会带大家一步步梳理 开始流式的相对位置更新所需要的步骤 最后我会说一些 大家可以在应用软件中采取的最佳做法 那就开始吧 (近距离交互框架) 近距离交互为你的 app 提供了两种主要的输出 设备间的距离测算 和他们之间的相对方向的测算 所以当你的 app 正在运行一个近距离交互会话时 它能够提供一串持续的流式更新 其中包含距离和方向信息 如幻灯片中所示 这些更新是双向的 也就是会话的两端 都在同时获知对方的相对位置 你的 app 不仅限于与一台设备进行交互 每台设备都可以同时运行多个会话 每个对话匹配一个不同的对等方 这个图像中 我展示了四台设备彼此之间的交互 它们各自都有三个会话在并行
现在我们来说说实现这项功能的接口 你需要先创建一个近距离交互会话对象 所有的近距离交互都被封装在会话中 与其它的 Apple 框架 比如说 ARKit 十分相似 你要为你的会话对象 提供相应的运行配置 比如说有两位或以上用户 正在运行你的 app 他们想通过某种空间上的方式 来进行彼此间的交互 实现这一点之前 你的 app 需要让双方的系统知道 如何识别出位于附近的另一台设备 (设备需要知晓彼此) 发现对等方是一个很关键的概念 设备之间 可以使用一种叫做发现令牌的东西 来通过保护隐私的方式发现彼此 (NIDiscoveryToken 介绍) 发现令牌是为特定近距离交互会话中 给定的一台设备 随机生成的一个标识符
发现令牌有使用时效 而这个使用时效相当于会话本身的长度 也就是说一旦你终止了会话 或者用户退出了你的 app 任何会话以及它相关的令牌也随即失效 令牌由系统生成 你可以通过会话对象在应用软件内接收到 你创建的每个会话 都有与之关联的独一无二的发现令牌 最终 你的 app 需要从会话对象中 复制发现令牌 然后在希望进行交互的用户间共享
关于这一点 我们来进行详细讲解 (通过 app 的网络层进行令牌交换) 比方说你的 app 在双方的设备上运行 并且你的 app 有某种网络层 可以使设备之间进行对话 通过你的网络层 将发现令牌从一台设备发送给另一台 并且在另一端也进行同样的操作 (向你发送我的发现令牌) 如何实现呢? 发现令牌的类型 遵从 NSSecureCoding 协议 也就是说你可以使用 app 可用的任何传输技术 将它轻松编码 然后递送出去 比如 你可以使用 Apple 的 MultipeerConnectivity 框架 如果适用于你的 app 的话 还可以通过 Cloud
再回到这个方块图 你的 app 交换完成的发现令牌 会进入会话配置 这个配置是由“run”方法为会话提供的
我们来看一下代码
这里的短代码片段 展示了让你的 app 成功运行会话的所有必要操作 首先 创建一个会话对象 在后台 这个调用 会对运行一个会话需要的所有资源 进行分配 里面就包括一个发现令牌
下一步 为了能从系统接受回调 需要设置会话的委托方
接着要交换会话特定的发现令牌 这需要通过 app 的网络层来完成 令牌交换步骤完成后 紧接着要创建一个会话配置 最后 运行带有配置的会话 (会话运行中) 我们继续向下构建来与代码相匹配 会话需要一个委托方来提供更新 在调用“run”之后 你的委托方开始收到有关附近对象的更新 这是近距离交互会话的基本结构
该看看演示版本了 我们来看一个有趣的小 app 它就用到了距离和方向
Monkey Time
我这里有一个 app 我背后桌上的手机上也在运行这个 app 我已经开始会话了 来看屏幕上显示的内容 我们能看到顶部显示了距离测算 而且在持续更新 我们的猴子小朋友在这里 他遮住了眼睛 那么现在我要靠近那台手机 看看会发生什么
(回顾) 好的 我们刚才讲了很多新内容 所以现在来回顾一下 要想运行一个会话 首先要为每个对等方创建一个会话对象 并与相应的对等方交换令牌
令牌交换完成后 创建一个会话配置 要想开启流式更新 需要使用配置来运行会话 你还可以将会话暂停 稍后可以再次调用“run”方法来恢复会话 我之前提到 调用“run”之后 你就会开始从会话中接收到更新 以这个为前提 我们来详细说说 你可以在 app 中实行的委托方回调
这里是会话委托方协议 你的 app 通过实行 didUpdate 回调 来接受附近设备的更新 这里还涉及到几个有趣的方法 每当系统不再与附近对象进行交互 都会通知你的 app 这个通知会附带一个原因 你可以预期到的两个原因 为“超时”或“对等方结束” 它们的差异表现在一些重要方面 超时表示在一段时间内 会话中没有进行任何活动 比如当设备之间距离太远时 就可能发生这种情况 而对等方结束 表示对方明确终止了会话 这里要注意 这个通知是尽可能传达的 所以不是每次都会接收到 以上是附近对象移除的原因 最后三个委托方回调 与会话的生命周期有关 只要出现了阻止会话运行的条件 你的委托方就会收到中断通知 (会话中断) 比如当你的 app 不再是前台运行时 会话就会中断 你需要等到中断结束的通知 才能继续使用 (等待 sessionSuspensionEnded 回调后继续) 当你终于收到中断结束的回调后 会话并不会自动恢复 这使你能够在此时对会话的走向做出决定 如果你想恢复会话 可以在两端调用“run” 这就和第一次开始会话时一样 只不过这一次不用再交换发现令牌
最后同样重要的是 sessionDidInvalidate 回调 它会通知你的 app 有关会话终止的情况 由于特定的错误情况和资源限制 会话的终止会关联一个错误代码 已经终止的会话无法再次运行 相关联的令牌也不能被再次使用 要想重新开始交互 你需要创建一个新会话 并重新交换发现令牌
以上都是你的 app 可能会从系统处 接收到的各种委托方回调 (运行会话) 现在回到这张完整的图 这张图表示单个会话 我之前提到 你的 app 可以同时运行多个会话 运行多个会话时正如图中所示 你为每个对等方创建一个会话 而且你可以在必要时 重复使用 app 的其它部分 举个例子 这里我为所有会话使用了同样的委托方
只要坚持“一个会话配一个对等方”原则 同时管理多个对话就会变得简单直观 你可以 为每台附近的设备创建一个交互会话 来与多台设备同时进行交互 你可以将它视为与另一台设备间的对话 我们建议将会话 存储在类似字典的数据结构内 以便将你的 app 中 关于对等方用户的记录 与他们相应的近距离交互会话对照起来
好的 你现在已经建立并运行了几个会话 并且开始接收到关于附近对象的更新了 现在我要深入讲解附近对象所包含的内容 以及你可以如何在应用软件中使用它们 (深入:NINearbyObject) 每个附近对象都带有三个属性 你在配置中提供给会话的发现令牌 这个属性是为了让你将这些更新 连回到当初你接收到令牌的用户身上 下一项属性是距离 它包含了以米为单位的距离测算 表明两台设备间相距多远 最后一项属性是方向 它包含了一个三维单位矢量 以本地设备作为参照 指向另一台设备
这是相应的代码 发现令牌识别出这个附近对象 你与对象之间以米为单位的距离测算 以及表示与对象之间相对方向的矢量 我想提醒你注意的是 距离和方向属性可为空 从这里可以完美过渡到 我接下来想要请大家牢记的最佳做法 (最佳做法) 首先 要时刻确认硬件支持 在你的 app 中有策略地选择一个位置 来检查它是否支持近距离交互 确保在必要时退一步 采用一个不同的用户体验 接着 要熟悉定向视野这个概念 (定向视野) 类似其它硬件传感器 比如说相机 近距离交互所使用的硬件也依从于视野 从概念上说 视野是一个如图所示的圆锥体 从手机背面向外发散 它大致与 iPhone 11 超广角相机的视野相当
当与你交互的设备在这个视野内时 距离和方向的更新 都将如预期的一样具有极高的准确性 但如果一台设备在定向视野之外 你的 app 或许会继续更新距离 但不会再更新方向 当你开发 app 以及设计用户体验时要谨记这一点 下一点是了解实际设备方向的影响 为了获得最佳性能 所有设备都应该保持在竖屏方向 (不一致的方向) 一台设备是竖屏 而另一台是横屏 会限制测算的可得性 这是你无论如何都要避免的 所以要确保你的 app 不会使用户遇到这种情况 接下来 要注意遮挡 彼此都在清晰视线内的设备 将获得最佳性能 你可以将其想象为设备之间互相注视对方 设备之间的砖墙、人或者任何人事物 都可能降低测算的可得性 (检查距离和方向的可空性) 我之前提到过 附近对象的距离和方向属性可为空 所以我上述提到的情况中 只要有一项无法达成 这些区域都将为空 你需要为此做好准备 并在你的应用软件中 依情况处理可空性 至于开发过程的最佳做法 你可以充分利用 Xcode 中原生集成的模拟器支持 两个或以上的模拟器窗口之间的距离 和方向更新会触发与实际设备上运行的 相同的应用软件代码 我们非常乐意将它发送给你 同时希望这项功能 可以简化并加快你的开发过程
这就是我们对于最佳做法的最终建议 借助已有的原生 Xcode 支持 来模拟近距离交互 (总结) 今天我们介绍了近距离交互 它使你能够将空间感知添加进应用软件 并基于设备的相对位置信息 创建出新型的用户交互方式 感谢大家参与今天的讲座 我们十分期待你用它构建出的新作品
-
-
6:01 - Basic session setup
// A session instance. Store in whichever data structure makes the most sense for your app. var niSession: NISession? // Instantiate a new session object and set the session's delegate. func prepareMySession() { // Verify hardware support. guard NISession.isSupported else { print("Nearby Interaction is not available on this device.") return } // Create a new session for each peer. niSession = NISession() // Set the session’s delegate. niSession?.delegate = self // This class of 'self' needs to conform to NISessionDelegate. } // Share the encoded discovery token to the peer you intend to interact with. func sendDiscoveryTokenToMyPeer(myPeer: Any /* change to whichever type represents peers in your app */) { guard let myToken = niSession?.discoveryToken else { // The session object is not initialized or has been invalidated. return } if let encodedToken = try? NSKeyedArchiver.archivedData(withRootObject: myToken, requiringSecureCoding: true) { <# share token using your app's networking layer #> } } // Once you receive a token from the peer, create a configuration and run the session. // This functions shows how to decode token data that was previously encoded using NSKeyedArchiver. func runMySession(peerTokenData: Data) { guard let peerDiscoveryToken = try? NSKeyedUnarchiver.unarchivedObject(ofClass: NIDiscoveryToken.self, from: peerTokenData) else { print("Unexpectedly failed to decode discovery token.") return } // Create a session configuration using the discovery token received from the peer. let config = NINearbyPeerConfiguration(peerToken: peerDiscoveryToken) // Run the session with the configuration. niSession?.run(config) }
-
12:40 - Verify hardware support
// Always verify hardware support. guard NISession.isSupported else { print("Nearby Interaction is not available on this device.") return }
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。