Highlight
Apple 在 2020 年为 ClassKit 增加活动缩略图、摘要、建议年龄、建议完成时间和进度报告能力,并推出 ClassKit Catalog API,让公开学习内容可以通过 Web 服务预先进入 Schoolwork 的活动选择器。
核心内容
教育类 app 接入学校场景时,难点常常在内容交付之后。教师需要知道哪个活动适合布置,学生需要从 Schoolwork 直接进入正确位置,开发者还要在保护学生隐私的前提下报告进度。ClassKit 原本已经能把 app 内的学习活动暴露给 Schoolwork,但 2020 年的重点变成了两个更具体的问题:活动要有足够信息供教师判断,内容目录要能脱离 app 更新独立管理。
演讲先从 Schoolwork 的 App Activity Chooser 讲起。教师创建 handout 时,会在选择器里看到支持 ClassKit 的 app 和活动层级。一个活动可以是书里的章节、播客里的媒体流、测验或 quiz。ClassKit 用 CLSContext 表示这些活动,并通过 Main App Context 组织成树状结构。只有被教师分配的活动才会报告学生进度,这一点是 ClassKit 隐私模型的核心。
新的 CLSContext 元数据让活动更像教师能直接使用的教学材料。缩略图、摘要、建议年龄、建议完成时间,以及活动会报告哪些进度数据,都会显示在 Schoolwork 中。教师看到一个测验时,不需要先打开 app 探路,就能判断它适不适合这一节课。
后半场转到 ClassKit Catalog API。过去,公开内容通常要靠 app 在本机创建 CLSContext,教师或学生设备使用到 app 后才逐步生成目录。新的 Web 服务让开发者把现有 CLSContext 层级翻译成 JSON 并上传。Apple 会在 Schoolwork 引用 app 时生成对应 context。公开内容走 Catalog API,动态生成或用户专属内容继续用原生 ClassKit API 上报。
详细内容
给活动补齐可见元数据
(06:25)CLSContext 仍然是活动的基本单位。2020 年新增的重点是让一个 context 在 Schoolwork 里带上教师能理解的信息。演讲用 Measurements Quiz 做例子,先创建 quiz context,再写入摘要和缩略图。
// Create a context for quiz
let quizContext = CLSContext.init(type: CLSContextType.quiz, identifier: "science_Investigation_quiz", title: "Measurements Quiz")
// Add a summary describing this context
quizContext.summary = "A short quiz to test how much students know about scientific measurements and how to examine and analyze scientific data."
// Add a thumbnail for this context — ClassKit will downsize thumbnails to 330 x 330 px if needed
let bundle = Bundle.main
if let resourceURL = bundle.resourceURL {
let imageURL = resourceURL.appendingPathComponent("measurements_quiz.jpg")
if let thumbnail = thumbnailFromImage(atURL: imageURL) {
quizContext.thumbnail = thumbnail
}
}
关键点:
CLSContext.init把测验声明成一个可被 Schoolwork 浏览的 quiz 活动。summary是面向教师和学生的描述文字,应该说明这个活动实际考察什么。thumbnail会出现在活动选择流程里,ClassKit 会按需把图片缩小到 330 x 330 px。- 代码从 app bundle 里取
measurements_quiz.jpg,再交给thumbnailFromImage(atURL:)生成缩略图。
控制缩略图的内存成本
(06:52)演讲特意拆开缩略图函数,是因为直接把大图加载成 UIImage 可能显著增加 app 内存。CoreGraphics 可以按目标尺寸生成缩略图,适合在活动目录初始化时使用。
// Create a thumbnail of maximum dimension 330 x 330 px from an image file
func thumbnailFromImage(atURL: URL) -> CGImage? {
if let imageSource = CGImageSourceCreateWithURL(atURL as CFURL, nil) {
let thumbnailOptions = [kCGImageSourceCreateThumbnailFromImageAlways as String: true,
kCGImageSourceThumbnailMaxPixelSize as String: 330]
return CGImageSourceCreateThumbnailAtIndex(
imageSource, 0, thumbnailOptions as CFDictionary);
}
return nil
}
关键点:
CGImageSourceCreateWithURL直接从文件 URL 创建图片源。kCGImageSourceCreateThumbnailFromImageAlways要求系统生成缩略图。kCGImageSourceThumbnailMaxPixelSize把最大边限制为 330,与 Schoolwork 使用的尺寸一致。- 函数返回
CGImage?,可直接赋给CLSContext.thumbnail。
标注年龄、时间和进度类型
(07:59)教师选择活动时,年龄和预计时间是决策信息。ClassKit 用范围表达这两个值:一个测验适合 9 到 11 岁,预计 15 到 20 分钟完成。
// Add suggested age range appropriate for the content — ages 9 to 11 years
quizContext.suggestedAge = NSRange(9...11)
// Add suggested time to complete this quiz — 15 to 20 minutes
quizContext.suggestedCompletionTime = NSRange(15...20)
关键点:
suggestedAge用NSRange表示内容适合的年龄段。suggestedCompletionTime用NSRange表示预计完成时间,单位来自 ClassKit 对该属性的定义。- 这两个字段不改变 app 内部逻辑,但会影响教师在 Schoolwork 里理解活动。
(08:15)进度报告也需要先声明能力。演讲举了两个能力:百分比进度和使用提示次数。details 是用户可见文字,所以需要按当前 locale 在运行时本地化。
// Add progress reporting capabilities
let reportingPercentDetails = "Reports percentage of progress"
let reportingCapabilityPercent = CLSProgressReportingCapability.init(
kind: .percent,
details: reportingPercentDetails)
let reportingQuantityDetails = "Reports number of hints used"
let reportingCapabilityQuantity = CLSProgressReportingCapability.init(
kind: .quantity,
details: reportingQuantityDetails)
quizContext.addProgressReportingCapabilities([reportingCapabilityPercent,
reportingCapabilityQuantity])
关键点:
CLSProgressReportingCapability用kind描述数据类型,用details描述这个数据对用户意味着什么。.percent适合完成百分比,.quantity适合提示次数这类计数。addProgressReportingCapabilities把这些能力挂到 quiz context 上,Schoolwork 才能在活动详情里展示可报告的进度种类。details会被用户看到,演讲明确要求运行时按当前 locale 本地化。
管理 context 树和 Catalog API
(10:01)Apple 给出的本地管理建议很直接:创建 context 时尽量补齐元数据;如果发现旧版本 app 保存的 context 缺字段,就更新缺失属性;如果 app 已经不再支持某个旧 context,就删除它。使用 context provider app extension 的项目,也要同步更新扩展。
(11:12)CLSContext 还增加了几个结构性能力:只读的 identifierPath 返回 context 的完整 identifier path;新的 context type 包括 course 和 custom;自定义 context 可以设置名称;isAssignable 可以把容器节点标记成不可分配活动。演讲中的书籍节点就是容器:它用来承载章节,不应该被教师整本书分配。
(14:00)ClassKit Catalog API 把内容管理放到 Web 服务里。开发者把 app 里的 CLSContext 层级翻译成 JSON payload,上传到 api.classkit-catalog.apple.com/v1。公开内容适合这种方式;私有、动态生成、用户专属的 CLSContext 继续走原生 API。
(15:40)Catalog API 的 POST 请求分成 contexts 和 thumbnails 两类。contexts 请求包含 environment 查询参数、Content-Type、Authorization,正文是一组要创建或更新的 contexts。每个 context 分成 data 和 metadata:data 来自 CLSContext 字段,metadata 包含 locale、minimumBundleVersion 和 keywords。
(18:12)contexts endpoint 有三个操作边界。一次 POST 最多 200 个 contexts;提交子节点前要先提交祖先节点;删除一个 context 会连同后代一起删除。thumbnail endpoint 要使用 PNG 或 JPEG,尺寸按 330 x 330 px 准备,并且先上传 contexts,再上传 thumbnails,避免缩略图没有任何 context 引用。
(21:19)认证使用 JSON Web Token。开发者在 Apple Developer portal 创建 ClassKit Catalog API key,用 key ID、team ID、UUID、签发时间和过期时间组成 header 与 payload,再用 ECDSASHA256 签名。请求里的 Authorization header 需要以 Bearer 前缀携带 token。
核心启发
1. 做一个教师友好的活动目录
做什么:为 app 里的每个章节、练习和测验建立 CLSContext 层级,并补齐 summary、thumbnail、suggestedAge 和 suggestedCompletionTime。
为什么值得做:Schoolwork 的活动选择器会展示这些信息,教师不需要先进入 app 才能判断活动是否适合作业。
怎么开始:先从最常被布置的 5 到 10 个活动开始,按 Main App Context 到章节、练习、测验的顺序建立 context 树,再用官方缩略图代码控制图片尺寸。
2. 做一个只报告作业内进度的测验模块
做什么:把测验进度拆成百分比、提示次数、正确/错误得分、总分等能力,并在 CLSContext 上声明。
为什么值得做:ClassKit 的隐私模型只报告被分配活动的进度,适合学校场景里对学生数据最小化的要求。
怎么开始:先接入 CLSProgressReportingCapability 的 .percent 和 .quantity,把用户可见的 details 文案接入现有本地化系统。
3. 做一个不可分配容器节点整理内容
做什么:把书籍、课程或单元作为容器 context,把真正要布置的章节、测验放在子节点。
为什么值得做:教师看到的是结构清楚的目录,同时不会误把整本书或整个课程作为作业发给学生。
怎么开始:为容器节点设置新的 context type,必要时使用 custom 和自定义名称,再把 isAssignable 设为 false。
4. 做一条 Catalog API 发布管线
做什么:把公开课程目录从 app 发布流程里拆出来,通过 ClassKit Catalog API 上传 contexts 和 thumbnails。
为什么值得做:公开内容发生变化时,可以更新 Schoolwork 里的可发现目录,不必等待 app 新版本发布。
怎么开始:先把已有 CLSContext 树导出成 JSON 结构,按 200 个 contexts 一批提交;开发环境用 environment 参数测试,确认后再推到 production。
关联 Session
- What’s new in education — 从 Schoolwork 2.0、ClassKit、assessment 和学校设备管理角度看教育 app 的整体接入路线。
- What’s new in assessment — 补充考试 app 如何用 Automatic Assessment Configuration 控制受测设备环境。
- Create Swift Playgrounds content for iPad and Mac — 继续看学习内容作者如何为 iPad 和 Mac 设计 Swift Playgrounds 课程。
- Swan’s Quest, Chapter 4: The sequence completes — 用 Swift Playgrounds 的章节示例连接教育内容、代码练习和可下载 playground book。
评论
GitHub Issues · utterances