Files
ios/Xuxucheck/README.md
T
admin d6aeede2bc 导入 XuXuCheck 工程(iOS 干化学尿液试纸分析 App)
从桌面工程复制而来,作为本仓库的 Xuxucheck/ 子目录。

为控制仓库体积做了两处删减:
- 移除 Frameworks/opencv2.xcframework 下的两个 visionOS 切片
  (xros-arm64、xros-arm64-simulator,合计约 106 MB),并同步删掉该
  xcframework 内 Info.plist 里对应的两条 AvailableLibraries 记录,
  只保留 ios-arm64 与 ios-arm64_x86_64-simulator。
- 移除全部 .DS_Store 与 xcuserdata/。

已用 xcodebuild 从本目录完整编译验证:BUILD SUCCEEDED,
ProcessXCFramework 以 --platform ios 成功选中框架,产物含 3699 个 cv:: 符号
(OpenCV 确实链入),嵌入 framework 3 个,与移除无用 pod 之后的状态一致。

仓库约 206 MB,其中 OpenCV 203 MB、其余源码与依赖约 3 MB。
2026-09-23 14:17:31 +08:00

186 lines
9.5 KiB
Markdown

# XuXuCheck
干化学尿液试纸分析 App(iOS / SwiftUI)。用户用相机拍摄试纸,App 通过 C++/OpenCV 定位试纸、
跨 16 帧采样 16 个试剂垫,再把 HSV/Lab 测量值上传服务端。除相机与扫描流程外,其余界面
(产品介绍、记录、成员、我的)都是服务端渲染的网页,由 `WKWebView` 承载。
| | |
|---|---|
| Bundle ID | `com.niaodaifu.xuxu.XuXuCheck` |
| Deployment Target | iOS 18.4 |
| 开发语言 | Swift 5.0 + Objective-C++(OpenCV 桥接) |
| 界面语言 | 英文(App 内置)/ 中文(业务域) |
| 版本管理 | `https://git.china-planet.com/admin/ios.git` 的 `Xuxucheck/` 子目录 |
> **本目录是 git 仓库里的副本**,由桌面版工程复制而来,为控制仓库体积做了两处删减:
> 删掉了 `Frameworks/opencv2.xcframework/` 里的两个 **visionOS 切片**(`xros-arm64`、
> `xros-arm64-simulator`,合计约 106 MB)以及所有 `.DS_Store` / `xcuserdata/`。
> 切片是连同 xcframework 内的 `Info.plist` 一起删的,只保留 `ios-arm64` 与
> `ios-arm64_x86_64-simulator` —— **本工程只构建 iOS,不受影响**(已编译验证)。
> 桌面上的原始工程仍是完整四切片版本,两者内容一致,只有这一处差异。
## 一、环境要求
| 项 | 要求 |
|---|---|
| macOS | 任意较新版本 |
| **Xcode** | **16.3 或更高**(deployment target 为 iOS 18.4,需要 iOS 18.4 SDK)已在本机 Xcode 27.0(Build 27A266a)验证 |
| **CocoaPods** | **不需要安装** —— 依赖已随项目提供,见第三节 |
| iOS 真机 | 相机 / 扫描流程**必须真机**;模拟器只会显示空白相机分支 |
| Apple ID | 需要能用于签名的账号,见第四节 |
## 二、编译方式
**必须打开 `XuXuCheck.xcworkspace`,不是 `XuXuCheck.xcodeproj`。**
后者不带 Pods 依赖,打开会报一大堆找不到符号的错误。
```bash
open XuXuCheck.xcworkspace
```
图形界面:选中 XuXuCheck scheme 和目标设备 → ⌘R。
命令行(先用 `xcrun devicectl list devices` 查设备 id):
```bash
# 真机
xcodebuild -workspace XuXuCheck.xcworkspace -scheme XuXuCheck \
-configuration Debug -destination 'id=<设备 id>' \
-allowProvisioningUpdates build
# 只验证能否编译,不依赖具体设备
xcodebuild -workspace XuXuCheck.xcworkspace -scheme XuXuCheck \
-destination 'generic/platform=iOS' build
```
**第一次编译会比较久(数分钟)**:7 个 pod 全部从源码编译,加上大量 OpenCV 头文件。
这是正常的,不是卡住。
测试 target 目前是空壳(`XuXuCheckTests` 用 Swift Testing,`XuXuCheckUITests` 用 XCTest),
跑单个用例:
```bash
xcodebuild -workspace XuXuCheck.xcworkspace -scheme XuXuCheck \
-only-testing:XuXuCheckTests/XuXuCheckTests/example test
```
## 三、依赖已随仓库提供,无需恢复
### OpenCV
- 位置:`Frameworks/opencv2.xcframework`(203 MB)
- 切片:`ios-arm64`、`ios-arm64_x86_64-simulator`(桌面版工程另有 `xros-arm64`、
`xros-arm64-simulator` 两个 visionOS 切片,本仓库为控制体积已删除,见开头的说明);
两个都是 **静态库**,因此没有 Embed 阶段,**运行时不依赖任何 opencv 文件**(代码已编进 App)
- 工程中只有**一处**引用,在 `XuXuCheck.xcodeproj/project.pbxproj`:
```
path = Frameworks/opencv2.xcframework; sourceTree = "<group>"
```
- 工程里**没有** `FRAMEWORK_SEARCH_PATHS` / `HEADER_SEARCH_PATHS`:构建时 Xcode 的
`ProcessXCFramework` 会把对应切片拷进 DerivedData,编译器与链接器通过自动的
`-F$(BUILT_PRODUCTS_DIR)` 找到它
- `#include <opencv2/opencv.hpp>` 走的是 framework 式查找 → `opencv2.framework/Headers/opencv.hpp`,
所以不需要额外的头文件搜索路径
- ⚠️ **不要**把它改成指向 `~/Downloads/opencv2.framework`。那是 OpenCV 4.11.0 官方 fat 包
(含 `i386/armv7`,没有独立的模拟器切片),与本项目使用的自建 xcframework 不是同一个东西
- 框架包内是 macOS 经典的版本化布局(`opencv2`、`Headers`、`Resources` 都是指向
`Versions/Current/*` 的符号链接,`Versions/Current` 再指向 `A`),终点在包内,不指向任何外部目录
### CocoaPods
`Pods/` 目录已完整随项目提供(pod 源码、`Pods.xcodeproj`、`Target Support Files` 齐全),
所以:
- **不需要执行 `pod install`**,新机器**连 CocoaPods 都不用装**。工程里三个 `[CP]` 脚本阶段
都是纯 shell(`diff` 比对 lock + 运行生成的 `.sh`),构建时不调用 `pod` 命令
- 依赖清单(共 3 个):`Alamofire` **4.x(不是 5.x)**、`AlamofireObjectMapper` 5.2,
以及它带进来的 `ObjectMapper` 3.5
- 因为 Alamofire 是 4.x,代码里的 `Alamofire.request(...)` 和 `DataResponse<T>` 是**正确**写法,
不要"顺手"升级。**Alamofire 也升不动**:`AlamofireObjectMapper` 5.2.1 要求 `Alamofire ~> 4.7`,
要上 5.x 就必须先把它换成 `Codable`,牵连 6 个 `Mappable` 类、32 处 `<-` 和 6 处 `.responseObject`
- 原先还依赖 `ProgressHUD`、`SDWebImage` + `SDWebImageSwiftUI`、`WrappingHStack`,但 App 代码
从未 import 过任何一个(全仓零引用)。`use_frameworks!` 会把每个 pod 都做成动态 framework
并嵌进 `.app`,所以它们每次构建都要编译、启动时都要加载 —— 已移除,嵌入框架由 7 个/6.4 MB
降到 3 个/2.8 MB
- ⚠️ **改 `Podfile` 后跑 `pod install` 必须用 1.16.2**:
```bash
gem install cocoapods -v 1.16.2
pod install
```
用其它版本会重写 `Pods.xcodeproj`,可能引入不必要的差异
- ⚠️ **`pod install` 会重新生成 `Pods.xcodeproj`,这里曾经埋着一个雷**:podspec 自己声明的最低
部署目标是 8.0,而 Xcode 27 只接受 15.0~27.0,低于 15.0 会**在编译任何代码之前就报错**
(`The iOS deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of
supported deployment target versions is 15.0 to 27.0.x`)。原来的工程是**手工**把这 22 处改成
15.6 才能编译的,而手工改动每次 `pod install` 都会被覆盖 —— 也就是说以前任何人跑一次
`pod install`,这个项目就编译不过了,只是没人跑过。
现在改由 `Podfile` 末尾的 `post_install` 钩子统一设置,重新生成也不会丢。**不要把这段挪回
手工改工程文件**,那样等于把这个坑重新埋上
## 四、签名
当前配置:自动签名(`CODE_SIGN_STYLE = Automatic`),Team `BK4A926286`。
在另一台 Mac 或另一个账号上编译时,二选一:
1. **沿用同一团队** —— 把新机器的 Apple ID 加入团队成员,并在该 Mac 的 Xcode 里登录,
自动签名会签发新证书。
2. **换成自己的账号** —— 修改 `DEVELOPMENT_TEAM`,但**必须同时修改 Bundle ID**
(`com.niaodaifu.xuxu.XuXuCheck` 属于原团队),例如改成 `com.yourname.XuXuCheck`。
免费个人账号也可以跑起来。
常见报错与对策:
| 报错 | 原因与处理 |
|---|---|
| `No profiles for 'com.niaodaifu.xuxu.XuXuCheck' were found` 并伴随 `PLA Update available ... Account Holder ... must agree` | 团队协议未接受,会锁住该团队的证书/描述文件资源。只有 Account Holder 能在 developer.apple.com 后台处理 |
| `Your account already has an Apple Development signing certificate ... but its private key is not installed` | 指的是历史(常为已过期)证书的私钥不在本机钥匙串。通常新证书已可用;确认无用后可在钥匙串里删掉那张旧证书 |
| 编译到 `Embed Pods Frameworks` 时报 `errSecInternalComponent` | 钥匙串拒绝了 `codesign` 使用私钥。用 Xcode 图形界面编译一次并在弹窗点「始终允许」,或检查该证书私钥的「访问控制」 |
## 五、复制到另一台 Mac
**整包复制即可编译,不需要 `pod install`。** 因为 `Pods/`、opencv、工程文件里
**没有任何 `/Users/...` 绝对路径**(已逐文件核查),整个目录也不依赖项目之外的任何东西。
注意事项:
1. **不要放在 Desktop / Documents / Downloads** —— macOS 隐私保护会拦截 Xcode 和命令行对其的访问
(表现为 `Operation not permitted`)。建议放 `~/Developer/` 之类不设防的位置
2. 拷贝前建议删掉本机残留:各处的 `xcuserdata/`(工程里共 4 处,含个人窗口/断点状态)与 `.DS_Store`
3. 在新机器上打开 `XuXuCheck.xcworkspace`,签名按第四节调整
4. 首次编译同样需要数分钟
5. 目录体积约 **206 MB**(其中 opencv 203 MB、`Pods` 0.9 MB),传输较慢
## 六、目录结构
```
XuXuCheck/
├── XuXuCheck.xcworkspace ← 打开这个
├── XuXuCheck.xcodeproj
├── Frameworks/
│ └── opencv2.xcframework ← 309 MB,自带的 OpenCV
├── Pods/ ← 已随项目提供,无需 pod install
├── Podfile / Podfile.lock ← CocoaPods 1.16.2
├── XuXuCheck/ ← App 源码(SwiftUI + opencv/ 下的 C++ 管线)
├── XuXuCheckTests/ ← 空壳
├── XuXuCheckUITests/ ← 空壳
├── docs/ ← 专题说明(含实测数据)
├── CLAUDE.md ← 架构说明与非显而易见的坑
└── README.md
```
## 七、已知坑
- **Debug 产物是分裂的**:Xcode 16+ 的 debug-dylib 机制下,真实代码在
`XuXuCheck.debug.dylib`(约 10 MB),主可执行文件只有约 90 KB、只是个壳。
判断"OpenCV 有没有链进去"要看前者,别看错文件
- **模拟器没有相机**,扫描流程必须真机
- 本目录不是 git 仓库,没有历史可回溯,改动前请自行备份
- 更多架构说明见 `CLAUDE.md`;WebView 顶部/底部边距的处理与实测数据见
`docs/webview-safe-area.md`