AiGatewayService 使用了 @Optional() 导致不报错但始终为 null, sendMessage 永远走 fallbackReply。现在导入 AiModule 正确注入。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
4.5 KiB
4.5 KiB
iOS Integration Guide
概述
本文档描述如何将 zhixi-document-runtime 集成到 iOS App 中。所有命令已验证可执行。
环境要求
- Rust 1.96+ (stable)
- Xcode 15+
- iOS 16+ deployment target
1. 构建 Rust 库
# 添加 iOS target(首次)
rustup target add aarch64-apple-ios aarch64-apple-ios-sim
# 一键构建(含 XCFramework + Swift 绑定)
./scripts/build-ios.sh
# 或手动构建
cargo build --release --target aarch64-apple-ios -p zx_document_ffi
cargo build --release --target aarch64-apple-ios-sim -p zx_document_ffi
产物:
target/aarch64-apple-ios/release/libzx_document_ffi.a
target/aarch64-apple-ios-sim/release/libzx_document_ffi.a
2. 生成 Swift Binding
使用 UDL bindgen + proc-macro 混合模式:
# 通过 build-ios.sh 自动生成,或手动:
# 1. 编译 Rust(proc-macro 生成 C ABI 符号)
cargo build --release -p zx_document_ffi
# 2. 从 UDL 生成 Swift 绑定(类型 + FFI 调用封装)
uniffi-bindgen generate \
--language swift \
--out-dir bindings/ios/generated \
crates/zx_document_ffi/src/zx_document.udl
输出:bindings/ios/generated/zx_document.swift (~50KB)
UDL 定义类型和函数签名,
#[uniffi::export]proc-macro 生成 C ABI 分发符号,bindgen 生成 Swift 调用封装。两者协作,非 library 模式。
3. 创建 XCFramework
xcodebuild -create-xcframework \
-library bindings/ios/device/libzx_document_ffi.a \
-library bindings/ios/simulator/libzx_document_ffi.a \
-output bindings/ios/ZxDocumentRuntime.xcframework
产物:bindings/ios/ZxDocumentRuntime.xcframework
4. 引入 Xcode 项目
- 将
bindings/ios/ZxDocumentRuntime.xcframework拖入 Xcode 项目 - 将
bindings/ios/generated/zx_document.swift添加到项目 - Target → General → Frameworks, Libraries, and Embedded Content:确保
ZxDocumentRuntime.xcframework为Do Not Embed(静态库) - Build Settings → Library Search Paths:添加 framework 路径
5. Swift 调用 API
类型
import ZxDocumentRuntime
// 枚举类型
let type = MaterialType.markdown
let mode = PreviewMode.nativeReader
// 位置
let pos = ReadingPosition.markdown(blockId: "h1", scrollProgress: 0.5)
// 事件
let event = ReadingEvent.materialOpened(materialId: "abc", timestampMs: 1000)
// 锚点
let anchor = NoteAnchor.markdownBlock(materialId: "abc", blockId: "h1")
// 字典类型
let meta = ImageMeta(width: 800, height: 600, format: "png", fileSize: 12345)
let info = DocumentInfo(materialId: "abc", title: "doc.md",
materialType: .markdown, previewMode: .nativeReader,
fileSize: 1024, pageCount: nil, wordCount: 100, createdAt: nil)
错误处理
所有函数抛出 DocumentError:
do {
let path = "/path/to/file.md"
let type = try detectMaterialType(filePath: path)
print("Detected: \(type)")
} catch let error as DocumentError {
switch error {
case .fileNotFound: print("File not found")
case .unsupportedFormat: print("Unsupported format")
case .parseError: print("Parse error")
case .invalidEncoding: print("Invalid encoding")
case .ioError: print("IO error")
}
}
阅读事件集成
// Rust 生成事件 → Swift 缓存 + 上传
class ReadingEventCollector {
private var buffer: [ReadingEvent] = []
func collect() {
// Rust 侧事件暂存
}
func flush() {
// POST buffer → /reading/events
// clear buffer
}
}
6. 使用真实 XCFramework 的项目示例
见 bindings/ios/demo/ 目录,包含最小 SwiftUI App 示例:
MaterialReaderDemo.swift— 调用 detect_material_type 并展示结果Info.plist— App 配置
7. 常见问题
| 问题 | 解决 |
|---|---|
No such module 'zx_documentFFI' |
确保 XCFramework 已添加到 Link Binary with Libraries |
library not found for -lzx_document_ffi |
检查 Library Search Paths |
| Swift 类型不匹配 | 重新生成 zx_document.swift(UDL 更新后必须重新生成) |
| 模拟器 crash | 确保用的是 ios-arm64-simulator slice |
| 文件路径错误 | 确保路径字符串是 OS 路径而非 Rust 路径 |
| 大文件解析慢 | 在后台线程调用 Rust 函数 |
8. 当前验证状态
- ✅
cargo build --release --target aarch64-apple-ios通过 - ✅
cargo build --release --target aarch64-apple-ios-sim通过 - ✅ XCFramework 已生成
- ✅ Swift bindings 已生成(48KB, 所有类型)
- ✅
cdylib和staticlib两种产物类型