大多数浏览器和
Developer App 均支持流媒体播放。
-
借助 Genmoji 将表情引入 App
探索如何在 App 中生动呈现 Genmoji。我们将介绍如何渲染、存储并传输包含 Genmoji 的文本。如果你的 App 拥有自定文本引擎,我们还会介绍一些相关技巧,帮助你添加对 Genmoji 的支持。
章节
- 0:00 - Introduction
- 0:37 - Express yourself
- 1:17 - Emoji enhancements
- 2:17 - NSAdaptiveImageGlyph
- 3:15 - Adopting in your app
- 8:01 - Compatibility
- 9:10 - Advanced usage
- 10:33 - Wrap-up
资源
相关视频
WWDC24
-
下载
嗨 我叫 Aaron 是一名工程师 来自 Input Experience 团队 很高兴今天能与大家分享一些 激动人心的新方式 帮助你通过表情符号 增强 App 的表现力 在这个讲座中 我们将探讨 表情符号体验的最近更新 介绍用于发送自定 表情符号的新 API 并了解如何在 App 中 轻松地采用表情符号 之后 我们将深入了解 兼容性注意事项 甚至讨论一些自定 文本渲染的高级用例 表情符号无处不在 有什么理由不用呢
表情符号富有表现力 我常常可以用单个 表情符号来替代整段文字
它们灵活多用 如果一个表情符号无法清晰表达观点 可以组合使用适当的表情符号 完美表达
与文字结合使用时 表情符号的效果 甚至变得更好 因为它们也是文本 与图像不同 表情符号 是句子的一部分 可以调整它们的展示效果 来匹配周围的文字 今年 Apple 推出了一系列更新 让表情符号变得更加精彩 其中包括经过更新的表情符号键盘 不仅包含我们熟悉和喜爱的 标准表情符号 还结合了 现在可以用作表情符号的 个性化内容
这些个性化内容包括 贴纸、拟我表情、动话表情 以及 Genmoji 这是一种制作属于 自己的表情符号的全新方式
这只狗真酷 我知道有些人在想什么 传统的表情符号实际上不是图像 而是一个标准化的 Unicode 字符列表 以纯文本形式发送 由查看设备渲染成适当的图像 并以设备自己的字体呈现 就像任何其他文本内容一样 另一方面 像 Genmoji 这样的 个性化图像是独特的光栅化位图 无法用 Unicode 文本字符描述 那么它是如何运作的呢 我们推出了 NSAdaptiveImageGlyph 借助这个全新的 API 可以像 使用标准表情符号一样 使用 Genmoji 和其他个性化图像 NSAdaptiveImageGlyph 由标准图像格式提供支持 采用正方形宽高比 支持多种分辨率 并通过其他元数据进行增强 例如全局唯一且稳定的标识符 用于实现可访问性的内容描述 以及对齐指标 这些指标可确保 适当的图像布局和位置 以便图像 可以与常规文本一起使用 或在常规文本旁边呈现适当的格式 Genmoji 可以单独使用 也可以结合文本使用 你可以为它们设置格式、进行复制 和粘贴 甚至作为贴纸发送出去
任何支持富文本的位置 都支持 Genmoji 以及所有富有表现力的图像
下面我们来看看 在应用程序中支持 Genmoji 有多么简单 NSAdaptiveImageGlyph 由富文本视区提供原生支持 如果你的 App 已经支持富文本 只需启用 supportsAdaptiveImageGlyph 即可轻松开始使用
在 iOS 上 如果你的文本视区 已经有 PasteConfiguration 或者目标操作是支持 图像的粘贴操作 那么你甚至不需要手动启用 因为这些配置会默认启用 针对 Genmoji 和自适应 图像字形的支持 在 macOS 上 在文本视区中声明 importsGraphics 可实现相同的支持 我们来看一个例子
我有一个 App 可以让用户创建 和分享关于自己的宠物的回忆 我们的主文本区域 已经是一个富文本视区 在我们的持久模型中 由富文本数据提供支持 因此 这默认启用了 Genmoji 支持 直接就能使用 Genmoji
之所以能够使用 是因为 SecureCoding 和 Pasteboard 之类的 所有系统序列化框架都已经过更新 能够原生支持 NSAdaptiveImageGlyph 事实上 如果你的文本内容已经 由 NSAttributedString 提供支持 那就什么都不用做了 只需坐下来 开始自我表达 与处理任何富文本一样 只需将文本视区的内容 序列化为 RTFD 数据对象 并将它存储在数据库中 当需要再次显示内容时 只需反向进行这个过程 并使用之前存储的数据 创建一个属性字符串 就是这么简单 虽然使用起来很简单 但一定要记住 Genmoji 不是 Unicode 它们可能不适用于纯文本项目 例如电子邮件地址 和电话号码 但用户创建的很多其他内容 比如博文、标题和信息等 就非常适合使用 Genmoji 可以通过图像字形支持 栩栩如生地呈现这些内容 例如 我很想使用自定表情符号 让这个标题更加醒目 但数据目前存储为纯文本 最终会与后端服务器共享 从而显示在网页浏览器中 我们可以怎么做? 在使用纯文本或其他非 RTF 数据存储时 一种解决方案是 按照你目前为内嵌图像提供支持的 相同方式来处理图像字形 例如 我们可以将 Unicode 附件字符存储在 适当的文本位置 同时在纯文本数据字段中 引用图像字形的标识符 并将图像添加到图像存储中 请记住 由于 contentIdentifier 是唯一且稳定的 如果你已经存储了具有 这个标识符的图像字形 就不需要再次存储 你可以查看本次讲座中附带的代码 找到如何分解和重组 这些属性字符串的示例 做出这些变更后 我现在可以 将 Genmoji 添加到标题中 并看到它显示在我们的 主要条目以及列表中 但如果使用的是我之前提过的 网页界面 该怎么处理呢? 再简单不过了 要以 HTML 格式显示图像 应该 使用之前我们用来转换为 RTFD 的 相同的 data-from-range 方法 但这次我们将请求 HTML 文档类型 这将生成跨平台兼容的 HTML 这样一来 像 Webkit 之类的 支持“apple-adaptive-glyph” 类型的高级引擎 将显示内嵌文本的图像 就像显示标准表情符号一样 对于不支持图像字形的引擎 将改为显示这张备用图像 请注意 这里的备用文本源自 NSAdaptiveImageGlyph 的内容描述 无论浏览器中最终显示哪个来源 都会应用这个备用文本 如果你的 App 使用通信通知 你可以借助新的 UNNotificationAttributedMessageContext API 在通知中包含 Genmoji 和其他图像字形 对于推送通知 有效负载只需包含 可带有图像字形的富文本表示 我们建议你使用通知 服务扩展来解析富文本、 下载素材、创建带属性的正文 以及更新通知内容 只需使用包含图像 字形的属性字符串 来创建通知信息 并将它作为 attributedContent 进行传递以创建上下文 使用这个上下文来更新请求 最终调用处理程序 在了解 NSAdaptiveImageGlyph 的 一些高级用例之前 我们先来花点时间讨论 你需要针对 App 考虑的重要的 兼容性注意事项
就像这里显示的文本一样 图像字形携带重要的语义 如果无法正确传达 这些语义可能会丢失或被更改 因此 在不受支持的上下文中 必须格外谨慎地处理回退行为 不要简单地丢弃这些重要信息 这一点至关重要 如果你的 App 不支持内嵌图像 考虑使用源自 contentDescription 的文本表示 对于更加根本性的 不兼容问题 可以考虑干脆不在 不受支持的系统上打开这类文档
以 RTFD 格式存储的图像字形 经过编码 可向后兼容 任何富文本视区 包括那些 不能感知图像字形的视区 如果你在不受支持的 环境中共享 RTF 文档 比如旧版本的 App 或者在旧版操作系统上 运行的 App 图像字形会自动 回退为标准文本附件 虽然开始使用 Genmoji 的 最简单方式可能是启用富文本支持 但采用第三方数据格式 和完全自定文本引擎 可以完全支持图像字形 不仅所有 Apple 平台上的 现有 UI 文本元素中 都支持图像字形 包括 TextView、 内容可编辑的 WebView 和 SwitfUI.Text 还可以使用 TextKit 和 CoreText 等现有 Apple 框架 构建自定文本引擎 从而利用更新的文本渲染 API 为 Genmoji 提供自定解决方案 对于自定排版解决方案 CoreText 提供了 使用 NSAdadptiveImageGlyph 作为自适应图像提供程序的方法 可以查询这个提供程序 让它根据 当前字体的规格提供适当的 排版界限 它还提供一种在当前上下文中的 给定点渲染图像的方法 我们来详细了解一下运作方式 CTFontGetTypographicBoundsForAdaptiveImageProvider 会返回直线布局所需的规格 包括相对于基线上的 图像字形原点的高级宽度 当需要绘图时 CTFontDrawImageFromAdaptiveImageProviderAtPoint 会将图像放置在这些界限内 就是这么运作的!
所有 Apple 平台上都提供的 表情符号体验迎来了众多 令人激动的变更 这个讲座 只是简要介绍了其中一些内容 包括全新的表情符号键盘、 使用 Genmoji 创建自定表情符号 以及利用 NSAdaptiveImageGlyph 通过多种方式在 App 中 支持富有表现力的图像 无论是使用标准富文本视区 还是管理完全自定的 排版解决方案 我都建议你查看最新 SDK 了解如何轻松地使用 Genmoji 在 App 中开辟 自我表达的全新世界 谢谢观看
-
-
3:30 - Enable support for NSAdaptiveImageGlyph in a UITextView
let textView = UITextView() textView.supportsAdaptiveImageGlyph = true
-
4:41 - Read and write attributed string for serialization
// Extract contents of text view as an attributed string let textContents = textView.textStorage // Serialize as data for storage or transport let rtfData = try textContents.data(from: NSRange(location: 0, length: textContents.length), documentAttributes: [.documentType: NSAttributedString.DocumentType.rtfd]) // Create attributed string from serialized data let textFromData = try NSAttributedString(data: rtfData, documentAttributes: nil) // Set on text view textView.textStorage.setAttributedString(textFromData)
-
6:08 - Decompose and recompose an attributed string
// Decompose an attributed string func decomposeAttributedString(_ attrStr: NSAttributedString) -> (String, [(NSRange, String)], [String: Data]) { let string = attrStr.string var imageRanges: [(NSRange, String)] = [] var imageData: [String: Data] = [:] attrStr.enumerateAttribute(.adaptiveImageGlyph, in: NSMakeRange(0, attrStr.length)) { (value, range, stop) in if let glyph = value as? NSAdaptiveImageGlyph { let id = glyph.contentIdentifier imageRanges.append((range, id)) if imageData[id] == nil { imageData[id] = glyph.imageContent } } } return (string, imageRanges, imageData) } // Recompose an attributed string func recomposeAttributedString(string: String, imageRanges: [(NSRange, String)], imageData: [String: Data]) -> NSAttributedString { let attrStr: NSMutableAttributedString = .init(string: string) var images: [String: NSAdaptiveImageGlyph] = [:] for (id, data) in imageData { images[id] = NSAdaptiveImageGlyph(imageContent: data) } for (range, id) in imageRanges { attrStr.addAttribute(.adaptiveImageGlyph, value: images[id]!, range: range) } return attrStr }
-
6:30 - Convert NSAttributedString to HTML
// Converting NSAttributedString to HTML let htmlData = try textContent.data(from: NSRange(location: 0, length: textContent.length), documentAttributes: [.documentType: NSAttributedString.DocumentType.html])
-
7:33 - Support Genmoji in communication notifications
func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { ... let message: NSAttributedString = _myAttributedMessageStringWithGlyph let context = UNNotificationAttributedMessageContext(sendMessageIntent: sendMessageIntent, attributedContent: _message) do { let messageContent = try request.content.updating(from: context) contentHandler(messageContent) } catch { // Handle error } }
-
9:45 - Render NSAdaptiveImageGlyph in custom typesetting solution
// Find typographic bounds for image in NSAdaptiveImageGlyph let provider = adaptiveImageGlyph let bounds = CTFontGetTypographicBoundsForAdaptiveImageProvider(font, provider) // Draw it at the typographic origin point on the baseline CTFontDrawImageFromAdaptiveImageProviderAtPoint(font, provider, point, context)
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。