WWDC Quick Look 💓 By SwiftGGTeam
Share files with SharePlay

Share files with SharePlay

观看原视频

Highlight

iOS 17 新增的 GroupSessionJournal API 让 SharePlay 应用可以传输最大 100MB 的附件(图片、PDF、语音等),利用 Apple 云端基础设施实现端到端加密的快速传输,并自动处理迟到者的状态同步。

核心内容

GroupSessionMessenger 的局限

SharePlay 应用之前用 GroupSessionMessenger 同步状态,但它只适合传输小型消息数据。想象一下协作画图应用:画笔轨迹可以走 Messenger,但用户往画布上拖了一张照片,这条路就走不通了。

00:58GroupSessionJournal 填补了这个空白。它使用与 FaceTime 相同的 Apple 云端基础设施,多层技术叠加减少传输数据量和等待时间,而且全程端到端加密。

Journal 的工作方式

02:14GroupSessionJournal 绑定到一个 GroupSession,所有参与者共享同一个 Journal 实例。一个人在本地调用 add,所有人的 attachments AsyncSequence 都会收到新附件事件;调用 remove,所有人同步移除。

附件类型只需遵循 Transferable 协议,系统会处理剩下的传输逻辑。

两个关键设计约束

03:37)附件大小上限 100MB。这迫使开发者区分内容类型:用户生成的照片、PDF、语音备忘录适合走 Journal;电影等大文件应该走应用自己的服务器。

04:18)生命周期与 GroupSession 绑定。只要还有人在线,附件就保留;所有人都离开后自动清除。这意味着重要数据需要在 Session 结束前持久化到本地。

迟到者问题自动解决

04:47)以前新加入的人需要其他参与者重新发送状态数据。如果状态里包含大附件,每个人都得重新上传一遍。Journal 现在自动把已有附件同步给新加入者,不需要其他人重新上传。

详细内容

在 DrawTogether 中集成 Journal

Session 以 DrawTogether 应用为例,演示了四步集成:

第一步:定义数据模型

创建 CanvasImage 结构体来跟踪 Journal 中的图片:

struct CanvasImage: Identifiable {
    let id: UUID
    let image: UIImage
    var position: CGPoint
}

第二步:在 Canvas 模型中创建 Journal

class Canvas: ObservableObject {
    @Published var images: [CanvasImage] = []
    @Published var selectedImageData: Data?

    private var journal: GroupSessionJournal?

    func configureGroupSession(_ session: GroupSession<DrawTogether>) {
        // 创建 Journal
        journal = GroupSessionJournal(session: session)

        // 监听附件变化
        Task {
            for await attachment in journal!.attachments {
                await handleAttachment(attachment)
            }
        }
    }

    func addImageToJournal(_ imageData: Data) {
        guard let journal = journal else { return }

        // 创建 Transferable 附件并上传
        let attachment = TransferableAttachment(data: imageData, type: .image)
        journal.add(attachment)
    }
}

关键点:

  • GroupSessionJournal(session:) 用 GroupSession 初始化
  • attachments 是 AsyncSequence,用 for await 监听新附件
  • add() 上传附件后,所有参与者都会收到

第三步:添加图片选择按钮

import PhotosUI

struct ControlBar: View {
    @ObservedObject var canvas: Canvas

    var body: some View {
        HStack {
            // 其他按钮...

            PhotosPicker(selection: $canvas.selectedImageData,
                         matching: .images) {
                Image(systemName: "photo")
            }
        }
    }
}

第四步:在画布上显示图片

struct CanvasView: View {
    @ObservedObject var canvas: Canvas

    var body: some View {
        ZStack {
            // 绘制笔画...

            // 显示所有图片
            ForEach(canvas.images) { canvasImage in
                Image(uiImage: canvasImage.image)
                    .position(canvasImage.position)
                    .gesture(
                        DragGesture()
                            .onChanged { value in
                                canvasImage.position = value.location
                            }
                    )
            }
        }
    }
}

关键点:

  • PhotosPicker 是 SwiftUI 内置组件,iOS 16+ 可用
  • 图片位置用 DragGesture 实现拖拽
  • 所有图片状态通过 Journal 同步给所有参与者

附件处理流程

func handleAttachment(_ attachment: GroupSessionJournal.Attachment) async {
    do {
        let data = try await attachment.load(Data.self)
        if let image = UIImage(data: data) {
            let canvasImage = CanvasImage(
                id: attachment.id,
                image: image,
                position: .center
            )
            await MainActor.run {
                images.append(canvasImage)
            }
        }
    } catch {
        print("Failed to load attachment: \(error)")
    }
}

关键点:

  • attachment.load(Data.self) 异步加载附件数据
  • 加载完成后切回主线程更新 UI
  • 附件 ID 可用于后续移除操作

核心启发

  1. 做带图片协作的白板应用

    • 做什么:多人可以在同一块画布上贴图、标注、讨论
    • 为什么值得做:Journal 自动处理图片传输和同步,开发者只需要关注画布交互逻辑
    • 怎么开始:用 GroupSessionJournal 传输图片附件,用 GroupSessionMessenger 同步画笔轨迹
  2. 做共享相册的聚会应用

    • 做什么:一群人在活动或旅行中实时共享照片,所有人都能看到彼此刚拍的照片
    • 为什么值得做:Journal 的端到端加密和自动同步让照片共享既安全又即时
    • 怎么开始:照片选择后用 journal.add() 上传,监听 attachments 序列接收他人照片
  3. 做协作标注的文档审阅工具

    • 做什么:团队成员一起审阅 PDF 文档,各自添加批注和高亮
    • 为什么值得做:PDF 文件通常小于 100MB,适合走 Journal;批注数据走 Messenger,两者结合实现完整体验
    • 怎么开始:PDF 文件作为 Journal 附件传输,批注坐标和文本通过 Messenger 实时同步
  4. 做共享播放列表的音乐应用

    • 做什么:一群人共同编辑一个播放列表,每个人都可以添加歌曲
    • 为什么值得做:虽然音频文件本身不走 Journal,但专辑封面、用户备注等元数据可以走 Journal 快速同步
    • 怎么开始:用 Journal 同步封面图片和播放列表变更,用 Messenger 同步播放状态

关联 Session

评论

GitHub Issues · utterances