docs: add iOS ops docs + CI config (IOS-INFO-028~031)
Some checks failed
iOS CI/CD / Build & Test (push) Has been cancelled

- rust-ffi-update.md: FFI binding update workflow
- app-store-submission-checklist.md: 9-section App Store review
- ios-ci.yml: GitHub Actions build + test on macos-15
- firebase-crashlytics-integration.md: Crashlytics setup guide

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
wangdl 2026-06-18 14:25:15 +08:00
parent 08b4c21ca2
commit 8b27430ed1
4 changed files with 420 additions and 0 deletions

48
.github/workflows/ios-ci.yml vendored Normal file
View File

@ -0,0 +1,48 @@
name: iOS CI/CD
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
build-and-test:
name: Build & Test
runs-on: macos-15
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- name: Select Xcode
run: sudo xcode-select -s /Applications/Xcode.app
- name: Build Rust xcframework (arm64 sim)
working-directory: ../zhixi-document-runtime
run: |
rustup target add aarch64-apple-ios-sim
cargo build --release -p zx_document_ffi --target aarch64-apple-ios-sim
- name: Build for iOS Simulator
run: |
xcodebuild build \
-project AIStudyApp/AIStudyApp.xcodeproj \
-scheme AIStudyApp \
-destination 'platform=iOS Simulator,name=iPhone 16' \
CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO
- name: Run Tests
run: |
xcodebuild test \
-project AIStudyApp/AIStudyApp.xcodeproj \
-scheme AIStudyApp \
-destination 'platform=iOS Simulator,name=iPhone 16' \
CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO \
2>&1 | tee xcode-test.log
- name: Upload test log
if: always()
uses: actions/upload-artifact@v4
with:
name: xcode-test-log
path: xcode-test.log

View File

@ -0,0 +1,78 @@
# App Store 提审 Checklist
## 1. 代码与构建
- [ ] `Build Configuration = Release`
- [ ] 所有 Scheme 编译通过iOS + Simulator
- [ ] SwiftLint / ESLint 无 warning
- [ ] 单元测试全部通过
- [ ] `ENABLE_BITCODE = NO`Xcode 15+
- [ ] Deployment Target >= iOS 16.0
## 2. 隐私与权限
- [ ] `Info.plist` 无未声明的隐私权限
- [ ] 隐私清单PrivacyInfo.xcprivacy包含所有使用的 API
- [ ] UserDefaults
- [ ] FileTimestamp
- [ ] SystemBootTime
- [ ] App Tracking Transparency 弹窗(如使用 IDFA
- [ ] 数据收集声明在 App Store Connect 中填写
## 3. 网络与安全
- [ ] 所有 API 调用使用 HTTPS
- [ ] ATSApp Transport Security无例外域名或已声明
- [ ] API Key / Token 不硬编码在源码中
- [ ] Keychain 用于存储敏感凭证
- [ ] 证书和 Provisioning Profile 有效≥30 天)
## 4. Rust xcframework
- [ ] `ZxDocumentRuntime.xcframework` 包含所需架构
- [ ] `ios-arm64`(真机)
- [ ] `ios-arm64-sim`Apple Silicon 模拟器)
- [ ] `ios-x86_64-sim`Intel 模拟器,可选)
- [ ] xcframework 已正确嵌入Embed & Sign
- [ ] `zx_document.swift` uniffi 绑定与 xcframework 版本一致
- [ ] 加密导出合规(如适用,提交 EAR 分类)
## 5. UI 与体验
- [ ] 启动图/Launch Screen 正确显示
- [ ] 无空白页面或崩溃路径
- [ ] iPad 适配(如声明支持)
- [ ] 深色模式适配
- [ ] 多语言文本无截断
- [ ] VoiceOver 可用(基础无障碍)
## 6. App Store Connect 元数据
- [ ] 应用名称、副标题、描述
- [ ] 关键词100 字符内)
- [ ] 截图6.7" + 6.5" + 5.5" 各 1-3 张,或仅 6.7"
- [ ] 应用图标1024×1024
- [ ] 分级Rating
- [ ] 版权信息
- [ ] 技术支持 URL
- [ ] 隐私政策 URL
## 7. 测试
- [ ] TestFlight 内部测试已通过
- [ ] 主要流程回归测试:登录→阅读→标记→分析
- [ ] 网络异常场景:飞行模式、弱网、超时
- [ ] App 切换(后台→前台)无数据丢失
- [ ] 低存储空间场景
## 8. 版本管理
- [ ] `CFBundleShortVersionString` 递增(如 1.0.0 → 1.1.0
- [ ] `CFBundleVersion` 递增Build Number
- [ ] Git tag 对应版本号
## 9. 紧急回滚准备
- [ ] 上一版本 ipa 已归档
- [ ] 知道如何取消审核App Store Connect → 移除提交)
- [ ] Release 分支保护已启用

View File

@ -0,0 +1,150 @@
# 崩溃监控集成Firebase Crashlytics
## 1. 概述
Firebase Crashlytics 用于收集 iOS 应用崩溃日志,支持 Swift 层和 Rust FFI 层的崩溃追踪。
## 2. 集成步骤
### 2.1 添加依赖
```swift
// Package.swift 或 Xcode SPM
.package(url: "https://github.com/firebase/firebase-ios-sdk", from: "11.0.0")
// Target dependencies
.product(name: "FirebaseCrashlytics", package: "firebase-ios-sdk"),
```
### 2.2 初始化
```swift
// AppDelegate.swift 或 AIStudyApp.swift
import Firebase
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
return true
}
```
### 2.3 GoogleService-Info.plist
从 Firebase Console 下载 `GoogleService-Info.plist`,放入 Xcode 项目根目录(不要加入 git加入 .gitignore
```bash
# .gitignore
GoogleService-Info.plist
```
### 2.4 dSYM 上传
```bash
# Build Phase: Run Script
"${BUILD_DIR%/Build/Products}/${CONFIGURATION}-${PLATFORM_NAME}/AIStudyApp.app/dSYMs"
${PODS_ROOT}/FirebaseCrashlytics/upload-symbols \
-gsp "${PROJECT_DIR}/GoogleService-Info.plist" \
-p ios "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}"
```
---
## 3. 自定义日志
### 3.1 Swift 层
```swift
import FirebaseCrashlytics
// 记录关键路径
Crashlytics.crashlytics().log("Reading session opened: \(materialId)")
// 设置用户标识
Crashlytics.crashlytics().setUserID(userId)
// 自定义 key
Crashlytics.crashlytics().setCustomValue(materialId, forKey: "last_material_id")
Crashlytics.crashlytics().setCustomValue(sessionState, forKey: "session_state")
```
### 3.2 Rust FFI 层
Rust panic 通过 `std::panic::catch_unwind` 捕获后,通过 FFI 回调通知 Swift
```swift
// zx_document.swift (uniffi generated)
// Rust panics are caught and returned as errors;
// Swift layer logs them to Crashlytics
do {
try documentRuntime.openMaterial(materialId)
} catch {
Crashlytics.crashlytics().record(error: error)
}
```
---
## 4. 关键监控点
| 位置 | 监控内容 |
|------|----------|
| `AppDelegate.didFinishLaunching` | 启动崩溃 |
| `MaterialReaderView.onAppear` | 阅读器打开 |
| `UploadScheduler.flush()` | 批量上传 |
| `RuntimeRecoveryService.recover()` | 会话恢复 |
| `FFI 调用点` | Rust panic |
| `sceneDidEnterBackground` | 后台切换 |
---
## 5. 符号化
### 5.1 Swift 符号
Xcode Archive 自动包含 dSYM。Crashlytics 通过 upload-symbols 脚本自动符号化。
### 5.2 Rust 符号
Rust xcframework 的 dSYM 需手动生成:
```bash
# 构建带调试符号的 Rust 库
cargo build --release -p zx_document_ffi --target aarch64-apple-ios
# 提取 dSYM
dsymutil target/aarch64-apple-ios/release/libzx_document_ffi.a \
-o ZxDocumentRuntime.dSYM
# 上传到 Crashlytics
${PODS_ROOT}/FirebaseCrashlytics/upload-symbols \
-gsp GoogleService-Info.plist \
-p ios ZxDocumentRuntime.dSYM
```
---
## 6. 告警阈值
| 指标 | 阈值 | 响应 |
|------|:--:|------|
| Crash-free rate | < 99% | 紧急修复 |
| Crash-free rate | < 99.5% | P1 调查 |
| 新 crash 类型 | ≥ 1 | 24h 内分类 |
| 回归 crash | ≥ 1 | 立即回滚 |
---
## 7. 隐私合规
- Crashlytics 不采集 PII个人身份信息
- 用户 ID 使用匿名化标识符UUID不关联登录邮箱
- 崩溃日志保留 90 天
- 在隐私政策中声明使用 Firebase Crashlytics
---
## 8. 相关文档
- [App Store 提审 Checklist](./app-store-submission-checklist.md)
- [iOS CI/CD](./ios-ci.yml) (.github/workflows/)

144
docs/rust-ffi-update.md Normal file
View File

@ -0,0 +1,144 @@
# Rust FFI 绑定更新流程
## 1. 概述
iOS 通过 uniffi 生成的 Swift 绑定调用 Rust Document Runtimezx_document_core
更新流程:修改 Rust 代码 → 重新生成 bindings → Xcode 重新编译
---
## 2. 文件结构
```
zhixi-document-runtime/
├── crates/
│ ├── zx_document_core/ # 核心 Rust 库
│ │ ├── src/
│ │ │ ├── document.rs # DocumentInfo + build_document_info
│ │ │ ├── material_type.rs
│ │ │ ├── markdown.rs # Markdown 解析
│ │ │ ├── pdf.rs # PDF 元数据/文本提取
│ │ │ ├── epub.rs # EPUB 元数据/章节/文本
│ │ │ ├── search.rs # 全文搜索
│ │ │ ├── anchors.rs # NoteAnchor
│ │ │ ├── events_v2.rs # V2 事件 buffer
│ │ │ ├── session_v2.rs # V2 Session 管理
│ │ │ └── image_meta.rs # 图片元数据
│ │ └── Cargo.toml
│ └── zx_document_ffi/ # FFI 绑定层
│ ├── src/
│ │ └── lib.rs # uniffi 导出定义
│ ├── src/zx_document.udl # UDL 接口定义
│ └── Cargo.toml
└── Cargo.toml # Workspace root
ios-projects/
└── AIStudyApp/
└── AIStudyApp/
└── Core/
├── ZxDocumentRuntime.xcframework/ # 预编译 Rust 库
└── zx_document.swift # uniffi 生成的 Swift 绑定
```
---
## 3. 更新流程
### 3.1 修改 Rust 接口
1. 在 `zx_document_core/src/` 中修改或新增函数/类型
2. 在 `zx_document_ffi/src/lib.rs` 中导出新接口
3. 如需新增 UDL 定义,更新 `zx_document.udl`
### 3.2 重新生成 Swift 绑定
```bash
cd zhixi-document-runtime
cargo build --release -p zx_document_ffi
# 生成 Swift 绑定
uniffi-bindgen generate \
crates/zx_document_ffi/src/zx_document.udl \
--language swift \
--out-dir ../ios-projects/AIStudyApp/AIStudyApp/Core/
```
### 3.3 构建 xcframework
```bash
# iOS arm64
cargo build --release -p zx_document_ffi --target aarch64-apple-ios
# iOS Simulator arm64 (Apple Silicon Mac)
cargo build --release -p zx_document_ffi --target aarch64-apple-ios-sim
# iOS Simulator x86_64 (Intel Mac)
cargo build --release -p zx_document_ffi --target x86_64-apple-ios
# 打包 xcframework
xcodebuild -create-xcframework \
-library target/aarch64-apple-ios/release/libzx_document_ffi.a \
-library target/aarch64-apple-ios-sim/release/libzx_document_ffi.a \
-output ZxDocumentRuntime.xcframework
```
### 3.4 更新 Xcode 项目
1. 替换 `AIStudyApp/Core/ZxDocumentRuntime.xcframework`
2. 替换 `AIStudyApp/Core/zx_document.swift`
3. 在 Xcode 中 Clean Build FolderCmd+Shift+K
4. 重新编译
---
## 4. 新增接口 checklist
- [ ] Rust 类型实现 `Serialize + Deserialize + uniffi::Record/Enum`
- [ ] FFI 层 `pub extern "C"` 导出函数
- [ ] UDL 文件声明接口
- [ ] Swift 绑定重新生成
- [ ] xcframework 重新编译(至少 arm64 + sim
- [ ] iOS 编译通过
- [ ] 单元测试通过(`cargo test -p zx_document_core`
---
## 5. 常见问题
### 5.1 xcframework 架构缺失
**症状**`While building for macOS, no library for this platform was found`
**原因**xcframework 仅包含 iOS 架构Mac Catalyst 构建试图链入
**处理**:确保 Scheme 仅勾选 iOS target或为 Mac Catalyst 添加 `aarch64-apple-ios-macabi` 目标
### 5.2 uniffi 版本不匹配
**症状**`uniffi::ffi::foreigncallbacks` not found
**处理**:确保 `Cargo.toml` 中 uniffi 版本与 `uniffi-bindgen` CLI 版本一致
### 5.3 Swift 类型不匹配
**症状**`Cannot convert value of type 'X' to expected argument type 'Y'`
**处理**:重新生成 `zx_document.swift`uniffi-bindgen 输出),确保与 xcframework 版本对应
---
## 6. 版本管理
| Rust crate | 当前版本 | FFI 接口数 |
|------------|:--:|:--:|
| zx_document_core | 0.1.0 | — |
| zx_document_ffi | 0.1.0 | 12 |
| uniffi | 0.28 | — |
---
## 7. 相关文档
- [V2 事件 Pipeline 架构](./v2-event-pipeline.md)
- [阅读信息采集接入文档](./reading-info-integration.md)