IOS-INFO-038:AppContext 采集与上传上下文 #126

Closed
opened 2026-06-10 22:15:05 +08:00 by wangdl · 1 comment
Owner

目标

定义 iOS 上传阅读事件时需要补充的 AppContext,包括 platform、appVersion、clientTimezoneOffsetMinutes 等字段,供 Rust Event → UploadItem 映射使用。

需要采集的字段

  • platform
  • appVersion
  • buildNumber
  • clientTimezoneOffsetMinutes
  • locale?
  • deviceType?
  • osVersion?

字段来源

platform: iOS 固定为 ios,或根据运行环境区分 ios / ipadOS

appVersion: Bundle.main.infoDictionary["CFBundleShortVersionString"]

buildNumber: Bundle.main.infoDictionary["CFBundleVersion"]

clientTimezoneOffsetMinutes: TimeZone.current.secondsFromGMT() / 60

locale: Locale.current.identifier

deviceType: phone / tablet,按 UIDevice 或当前适配逻辑判断

osVersion: UIDevice.current.systemVersion

规则

  1. AppContext 可在 App 启动时初始化。
  2. 上传前允许重新读取 timezone,避免跨时区长时间运行导致偏差。
  3. AppContext 不包含用户隐私字段。
  4. AppContext 不包含 token。
  5. AppContext 由 iOS 补充,不传给 Rust document runtime。
  6. IOS-INFO-012 映射 UploadItem 时必须使用 AppContext。

验收标准

  1. 新增 AppContext 类型。
  2. 可读取 platform。
  3. 可读取 appVersion。
  4. 可读取 buildNumber。
  5. 可读取 clientTimezoneOffsetMinutes。
  6. IOS-INFO-012 可使用 AppContext 生成 UploadItem。
  7. 有单元测试。
  8. 不依赖 API 实现。
## 目标 定义 iOS 上传阅读事件时需要补充的 AppContext,包括 platform、appVersion、clientTimezoneOffsetMinutes 等字段,供 Rust Event → UploadItem 映射使用。 ## 需要采集的字段 - platform - appVersion - buildNumber - clientTimezoneOffsetMinutes - locale? - deviceType? - osVersion? ## 字段来源 platform: iOS 固定为 ios,或根据运行环境区分 ios / ipadOS appVersion: Bundle.main.infoDictionary["CFBundleShortVersionString"] buildNumber: Bundle.main.infoDictionary["CFBundleVersion"] clientTimezoneOffsetMinutes: TimeZone.current.secondsFromGMT() / 60 locale: Locale.current.identifier deviceType: phone / tablet,按 UIDevice 或当前适配逻辑判断 osVersion: UIDevice.current.systemVersion ## 规则 1. AppContext 可在 App 启动时初始化。 2. 上传前允许重新读取 timezone,避免跨时区长时间运行导致偏差。 3. AppContext 不包含用户隐私字段。 4. AppContext 不包含 token。 5. AppContext 由 iOS 补充,不传给 Rust document runtime。 6. IOS-INFO-012 映射 UploadItem 时必须使用 AppContext。 ## 验收标准 1. 新增 AppContext 类型。 2. 可读取 platform。 3. 可读取 appVersion。 4. 可读取 buildNumber。 5. 可读取 clientTimezoneOffsetMinutes。 6. IOS-INFO-012 可使用 AppContext 生成 UploadItem。 7. 有单元测试。 8. 不依赖 API 实现。
wangdl added this to the M-IOS-INFO:学习信息采集、上传、继续学习与基础分析闭环 milestone 2026-06-10 22:15:05 +08:00
Author
Owner

开发完成评论

完成内容

  • 新建 Core/Models/AppContext.swift(87 行):
    • 7 个字段:platform, appVersion, buildNumber, clientTimezoneOffsetMinutes, locale, deviceType, osVersion
    • live() 工厂方法:从 Bundle.main + TimeZone.current + UIDevice.current 采集
    • refreshed() 方法:上传前重读时区偏移,避免跨时区漂移
    • platformValue() 区分 ios / ipadOS / macos
    • deviceTypeValue() 区分 phone / tablet
    • Codable + Equatable conformance
    • 不含 token / 隐私字段
  • 新建 AIStudyAppTests/AppContextTests.swift(85 行):
    • test_appContext_platform_is_ios_or_ipados
    • test_appContext_appVersion_notEmpty
    • test_appContext_buildNumber_notEmpty
    • test_appContext_timezoneOffset_isWithinRange
    • test_appContext_refreshed_updates_timezone
    • test_appContext_codable_roundtrip — JSON 编解码往返
    • test_appContext_equatable
    • test_appContext_no_token_field — 验证无 token
    • test_appContext_no_privacy_field — 验证无 idfa/idfv/pushToken/deviceId

修改文件

  • Core/Models/AppContext.swift:新建
  • AIStudyAppTests/AppContextTests.swift:新建

代码证据

  • Core/Models/AppContext.swift:33-44live() 从系统采集
  • Core/Models/AppContext.swift:47-51refreshed() 更新时区
  • Core/Models/AppContext.swift:54-62platformValue() 区分 idiom
  • AIStudyAppTests/AppContextTests.swift:46-52test_appContext_refreshed_updates_timezone
  • AIStudyAppTests/AppContextTests.swift:70-76test_appContext_no_token_field

验收标准逐项

  1. 新增 AppContext 类型 —
  2. 可读取 platform — platform 字段
  3. 可读取 appVersion — appVersion 字段
  4. 可读取 buildNumber — buildNumber 字段
  5. 可读取 clientTimezoneOffsetMinutes — + refreshed() 上传前更新
  6. IOS-INFO-012 可使用 AppContext — 7 个字段可供 UploadItem 映射
  7. 有单元测试 — 9 个测试
  8. 不依赖 API 实现 — 纯本地采集

是否建议进入 Review

  • 是(需 Xcode 编译验证,CLI 环境无完整 iOS SDK)
## 开发完成评论 ### 完成内容 - 新建 `Core/Models/AppContext.swift`(87 行): - 7 个字段:`platform`, `appVersion`, `buildNumber`, `clientTimezoneOffsetMinutes`, `locale`, `deviceType`, `osVersion` - `live()` 工厂方法:从 `Bundle.main` + `TimeZone.current` + `UIDevice.current` 采集 - `refreshed()` 方法:上传前重读时区偏移,避免跨时区漂移 - `platformValue()` 区分 ios / ipadOS / macos - `deviceTypeValue()` 区分 phone / tablet - `Codable` + `Equatable` conformance - 不含 token / 隐私字段 - 新建 `AIStudyAppTests/AppContextTests.swift`(85 行): - `test_appContext_platform_is_ios_or_ipados` - `test_appContext_appVersion_notEmpty` - `test_appContext_buildNumber_notEmpty` - `test_appContext_timezoneOffset_isWithinRange` - `test_appContext_refreshed_updates_timezone` - `test_appContext_codable_roundtrip` — JSON 编解码往返 - `test_appContext_equatable` - `test_appContext_no_token_field` — 验证无 token - `test_appContext_no_privacy_field` — 验证无 idfa/idfv/pushToken/deviceId ### 修改文件 - `Core/Models/AppContext.swift`:新建 - `AIStudyAppTests/AppContextTests.swift`:新建 ### 代码证据 - `Core/Models/AppContext.swift:33-44`:`live()` 从系统采集 - `Core/Models/AppContext.swift:47-51`:`refreshed()` 更新时区 - `Core/Models/AppContext.swift:54-62`:`platformValue()` 区分 idiom - `AIStudyAppTests/AppContextTests.swift:46-52`:`test_appContext_refreshed_updates_timezone` - `AIStudyAppTests/AppContextTests.swift:70-76`:`test_appContext_no_token_field` ### 验收标准逐项 1. 新增 AppContext 类型 — ✅ 2. 可读取 platform — ✅ `platform` 字段 3. 可读取 appVersion — ✅ `appVersion` 字段 4. 可读取 buildNumber — ✅ `buildNumber` 字段 5. 可读取 clientTimezoneOffsetMinutes — ✅ + `refreshed()` 上传前更新 6. IOS-INFO-012 可使用 AppContext — ✅ 7 个字段可供 UploadItem 映射 7. 有单元测试 — ✅ 9 个测试 8. 不依赖 API 实现 — ✅ 纯本地采集 ### 是否建议进入 Review - 是(需 Xcode 编译验证,CLI 环境无完整 iOS SDK)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: wangdl/ios-projects#126
No description provided.