d6aeede2bc
从桌面工程复制而来,作为本仓库的 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。
186 lines
9.5 KiB
Markdown
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`
|