# iOS Integration Guide ## 概述 本文档描述如何将 `zhixi-document-runtime` 集成到 iOS App 中。所有命令已验证可执行。 ## 环境要求 - Rust 1.96+ (stable) - Xcode 15+ - iOS 16+ deployment target ## 1. 构建 Rust 库 ```bash # 添加 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 混合模式**: ```bash # 通过 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 ```bash 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 项目 1. 将 `bindings/ios/ZxDocumentRuntime.xcframework` 拖入 Xcode 项目 2. 将 `bindings/ios/generated/zx_document.swift` 添加到项目 3. Target → General → Frameworks, Libraries, and Embedded Content:确保 `ZxDocumentRuntime.xcframework` 为 `Do Not Embed`(静态库) 4. Build Settings → Library Search Paths:添加 framework 路径 ## 5. Swift 调用 API ### 类型 ```swift 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`: ```swift 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") } } ``` ### 阅读事件集成 ```swift // 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` 两种产物类型