WWDC Quick Look 💓 By SwiftGGTeam
Add Shared with You to your app

Add Shared with You to your app

观看原视频

Highlight

Shared with You 是 iOS 15 引入、iOS 16 开放给第三方开发者的功能。它的核心理念是:朋友在 Messages 里发给你的内容,不应该沉没在聊天记录里,而应该在你打开相关 App 时自动浮现。


核心内容

朋友在 Messages 里发来一部剧、一篇文章或一首歌时,用户常常不在消费内容的场景里。演讲举的例子是:朋友推荐电视节目时,你正在超市买东西;等打开 TV app 想看节目时,那条消息已经被新的聊天淹没(00:46)。

Shared with You 解决的是这个断点。内容仍然从 Messages 分享出去,但当用户进入真正消费内容的 App,系统可以把这些链接重新浮现出来。iOS 15 先让 Safari、News、Music、Podcasts、TV app 和 Photos 接入;iOS 16 把 Shared with You 扩展到第三方 App、链接和内容(01:51)。

接入体验由两块组成。Shared with You shelf 放在 App 的浏览页面,展示 Messages 里分享过的内容;Shared with You attribution view 放在内容卡片或详情页,显示谁分享了它,并允许用户直接回到对应的 Messages 对话(02:16)。

底层依赖 Universal Links。系统通过 App 与网站的双向关联判断链接属于哪个 App;用户不需要提前授权,置顶链接本身就是把内容显示到 Shared with You 的隐式许可。开启自动分享后,同一 App 的后续内容也能自动进入列表(05:59)。

详细内容

09:27)接入顺序很明确:先支持 Universal Links,再在 Xcode 的 Capabilities 里添加 Shared with You Capability,最后在 App 中使用 Shared with You framework。

Universal Links 要求 App 和网站建立双向关联:App 添加 Associated Domains entitlement,网站提供 JSON 文件,声明哪些 URL 由 App 处理。用户点击共享链接时,系统会把 universal link 作为 user activity 交给 App delegate 处理(09:51)。

// 概念示例:Universal Links 的接入点
func application(
    _ application: UIApplication,
    continue userActivity: NSUserActivity,
    restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
    guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
          let url = userActivity.webpageURL else {
        return false
    }

    // 根据 url 导航到 App 内对应内容
    return openContent(for: url)
}

关键点:

  • NSUserActivityTypeBrowsingWeb:表示这次唤起来自 universal link。
  • userActivity.webpageURL:Shared with You 后续传给 App 的内容 URL 也建立在同一套链接归属机制上。
  • openContent(for:):这里是 App 自己的路由逻辑,负责把 URL 映射到内容详情页。
  • 这段是概念示例;演讲没有给出完整 App delegate 代码,只说明要响应系统提供的 user activity。

枚举 Shared with You shelf 的内容

10:42)iOS 16 新增 Shared with You framework,核心类有三个:SWHighlightCenterSWHighlightSWAttributionViewSWHighlightCenter 负责取得当前 App 的 Shared with You 内容;SWHighlight 包装一个被分享的内容 URL;SWAttributionView 负责显示分享者信息并连接回 Messages 对话。

// Enumerate Shared with You shelf

class SharedWithYouViewController: UIViewController, SWHighlightCenterDelegate {
    let highlightCenter = SWHighlightCenter()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        highlightCenter.delegate = self
    }
    
    func highlightCenterHighlightsDidChange(_ highlightCenter: SWHighlightCenter) {
        for highlight in highlightCenter.highlights {
            let highlightURL = highlight.url
            // Generate a rich preview for the Highlight
        }
    }
}

关键点:

  • SWHighlightCenter():创建读取 Shared with You 内容的入口对象。
  • highlightCenter.delegate = self:让当前控制器接收内容新增、删除或更新通知。
  • highlightCenterHighlightsDidChange:Shared with You 列表变化时调用。
  • highlightCenter.highlights:返回 SWHighlight 数组,App 可以保留旧数组并和新数组做 diff。
  • highlight.url:取出被 Messages 分享的内容 URL,用它生成 shelf 中的缩略图、标题和副标题。

在内容上显示 attribution view

13:01)Attribution view 是系统绘制的独立视图,显示分享者的姓名和头像,也会显示内容是否在 Messages 中被置顶。Apple 强调它是 out of process rendering:App 只拿到内容和视图,不能访问 Messages 收件人或具体对话(08:47)。

// Setting appearance of Attribution View

let attributionView = SWAttributionView()
attributionView.highlight = self.highlightCenter.highlights[index]
attributionView.preferredMaxLayoutWidth = maximumWidthForView

关键点:

  • SWAttributionView():创建显示分享来源的系统视图。
  • attributionView.highlight:把某个 SWHighlight 绑定到 attribution view;设置后会触发系统渲染分享者信息。
  • preferredMaxLayoutWidth:告诉视图最大可用宽度,视图会在这个空间内填充或适配。
  • 演讲提醒要给 attribution view 留出足够的垂直空间;高度会随 Dynamic Type 字号变化(14:18)。

控制对齐和显示场景

14:36)Attribution view 可以在最大宽度内设置水平对齐。演讲展示了 leading,同时说明还可以设为 centertrailing

// Horizontal Alignment for Attribution View

let attributionView = SWAttributionView()
attributionView.highlight = self.highlightCenter.highlights[index]
attributionView.preferredMaxLayoutWidth = maximumWidthForView
attributionView.horizontalAlignment = .leading

关键点:

  • horizontalAlignment:控制 attribution view 内容在最大宽度内的位置。
  • .leading:适合卡片底部这类从左侧开始阅读的布局。
  • preferredMaxLayoutWidthhorizontalAlignment 配合使用;前者定义可用空间,后者定义空间内的位置。

14:51displayContext 告诉系统用户正在怎样消费内容。默认值是 summary,表示内容处于摘要或浏览状态;用户正在看电影、听播客这类场景,应设置为 detail。这个反馈会影响 Siri Suggestions 对 Shared with You 内容的排序。

// Display Context for Attribution View

let attributionView = SWAttributionView()
attributionView.highlight = self.highlightCenter.highlights[index]
attributionView.preferredMaxLayoutWidth = maximumWidthForView
attributionView.horizontalAlignment = .center
attributionView.displayContext = .summary

关键点:

  • displayContext = .summary:表示内容以浏览摘要形式展示。
  • displayContext = .detail:适合用户正在实际消费内容的详情场景;演讲用看电影和听播客举例。
  • 这个属性要在视图加入 window 之前设置。
  • 系统还允许按背景选择 attribution view 的背景样式:单色背景可用 color,多色背景可用 material blur(15:47)。

把 Shared with You 菜单接到内容菜单里

16:21)Attribution view 自带上下文菜单,例如 Reply 和 Remove。用户点 Reply 或直接点 attribution view,都可以进入对应 Messages 对话;Remove 用来告诉 Shared with You 以后不要再展示这条内容。

App 也可以把 attribution view 的菜单项追加到自己的内容菜单中。Remove 的标题可以自定义,但字符串需要包含本地化后的 “Remove”。Safari 的例子是 “Remove Link”(16:48)。

// Add Shared with You Content Menu to your app’s content

let attributionView = SWAttributionView()
attributionView.highlight = self.highlightCenter.highlights[index]
attributionView.menuTitleForHideAction = "Remove Item"

let contextMenuConfig = UIContextMenuConfiguration(identifier: nil,previewProvider: nil) { [weak self] _ in
        let additionalMenu = attributionView.supplementalMenu
        // Append additionalMenu items to your content’s menu items
}

关键点:

  • menuTitleForHideAction:自定义 Remove 菜单项标题,适合写成 “Remove Link” 或 “Remove Item” 这类对象明确的文案。
  • UIContextMenuConfiguration:配置内容自身的上下文菜单。
  • attributionView.supplementalMenu:取得 Shared with You 提供的附加菜单。
  • Append additionalMenu:把系统菜单项追加到内容菜单的 inline 位置或末尾,保持用户在内容上长按时也能回复或移除。

核心启发

  • 做一个内容推荐回收站:在视频、播客、文章 App 的首页加入 Shared with You shelf,把用户尚未消费的 Messages 链接重新展示出来。入口是 SWHighlightCenter.highlights,用 highlight.url 生成内容卡片。

  • 给详情页加“谁推荐的”入口:在电影、音乐、食谱或商品详情页放置 SWAttributionView,让用户看到分享来源,并能直接回到 Messages 回复。入口是 SWAttributionView.highlight 和 attribution view 的点击交互。

  • 用 display context 改善排序反馈:浏览页使用 .summary,播放页或阅读页使用 .detail,让系统知道用户是否正在消费内容。入口是 attributionView.displayContext,设置时机是在视图加入 window 之前。

  • 统一内容长按菜单:把 Shared with You 的 Reply/Remove 菜单追加到 App 原有的卡片菜单里。入口是 attributionView.supplementalMenumenuTitleForHideAction

  • 优先修好 Universal Links 诊断:Shared with You 依赖 Universal Links 识别内容归属。可以先写一个内部检查页,验证 Associated Domains entitlement、网站 JSON 文件和 App 内 URL 路由是否完整,再接入 shelf 和 attribution view。

关联 Session

评论

GitHub Issues · utterances