# iOS / macOS 开发者指南 > 本项目同时支持 iOS、macOS、Android、鸿蒙(HarmonyOS) 四端。 > 鸿蒙端使用定制 Flutter SDK(`flutter-ohos`),在 `TargetPlatform` 枚举中新增了 `TargetPlatform.ohos`, > 并对大量三方库做了本地化适配。iOS/macOS 开发者需了解以下关键事项,避免踩坑。 --- ## 一、环境准备与项目拉取 ### 1.1 Flutter SDK 选择 | 平台 | 推荐SDK | 说明 | |---|---|---| | iOS / macOS | **官方 Flutter SDK** | 标准 stable/beta 渠道即可 | | 鸿蒙 | flutter-ohos 定制SDK | 包含 `TargetPlatform.ohos` 等扩展,仅在鸿蒙开发机上使用 | | Android | 官方 Flutter SDK | 同 iOS | > ⚠️ **iOS/macOS 开发使用官方 Flutter SDK 即可**,无需安装鸿蒙定制SDK。 > 不要用鸿蒙SDK编译iOS/macOS,反之亦然,SDK不兼容会导致编译错误。 ### 1.2 克隆仓库 ```bash # 克隆项目仓库 git clone <仓库URL> xianyan cd xianyan # 查看当前分支 git branch -a # 切换到开发分支(如需) git checkout feature/xxx # 或直接在 main 分支开发 git checkout main ``` ### 1.3 修改 pubspec.yaml 并安装依赖 MacBook Pro 端需要将 `pubspec.yaml` 中的本地包引用替换为远程版本号(详见 §2.2)。 ```bash # 1. 确认使用官方 Flutter SDK flutter --version # 应显示官方版本,非 flutter-ohos # 2. 修改 pubspec.yaml(参见 §2.2 替换清单) # 3. 获取依赖 flutter pub get # 4. iOS 编译验证 flutter build ios --no-codesign # 5. macOS 编译验证 flutter build macos # 6. 防止误提交 pubspec.yaml git stash push -m "macOS-local-pubspec" pubspec.yaml ``` --- ## 二、pubspec.yaml 与三方库 ### 2.1 MacBook Pro 端的核心原则 > **MacBook Pro 端不需要 `packages/` 目录,直接使用远程三方库即可。** 项目 `pubspec.yaml` 中的本地包引用(`path: packages/xxx`)是为鸿蒙端准备的。 MacBook Pro 端使用官方 Flutter SDK,需要将这些本地包引用替换为远程版本号。 **为什么不能直接用本地包?** 本地包中包含 `TargetPlatform.ohos` 引用(鸿蒙SDK新增的枚举值),官方 SDK 没有此值,会导致编译报错: ``` Error: The getter 'ohos' isn't defined for the class 'TargetPlatform' ``` 受影响的本地包有 5 个: | 包名 | 引用次数 | 引用类型 | |---|---|---| | flex_color_picker | 2 | `case TargetPlatform.ohos:` (switch) | | flutter_quill | 2 | `case TargetPlatform.ohos:` (switch) | | flutter_local_notifications | 8 | `== TargetPlatform.ohos` (if比较) | | mobile_scanner | 3 | `== / != TargetPlatform.ohos` (if比较) | | audioplayers | 1 | `!= TargetPlatform.ohos` (if比较) | **解决方案**:MacBook Pro 端使用远程版本,远程版本不含 `TargetPlatform.ohos`,编译正常。 ### 2.2 MacBook Pro 端 pubspec.yaml 修改指南 克隆项目后,需要修改 `pubspec.yaml`,将本地包引用替换为远程版本号。 #### 2.2.1 dependencies 区域 — 需要替换的包 将以下包从 `path: packages/xxx` 改为版本号: ```yaml # ❌ 原始写法(鸿蒙端) shared_preferences: path: packages/shared_preferences # ✅ MacBook Pro 端改为远程版本 shared_preferences: ^2.5.5 ``` **完整替换清单:** | 包名 | 远程版本号 | 说明 | |---|---|---| | shared_preferences | ^2.5.5 | 轻量KV持久化 | | flutter_secure_storage | ^9.2.4 | 加密安全存储 | | hive_flutter | ^1.1.0 | Hive Flutter适配 | | path_provider | ^2.1.5 | 系统目录路径获取 | | package_info_plus | ^10.1.0 | 应用包信息读取 | | connectivity_plus | ^7.1.1 | 网络连接状态监听 | | device_info_plus | ^13.1.0 | 设备硬件信息读取 | | permission_handler | ^12.0.1 | 运行时权限请求 | | flutter_local_notifications | ^21.0.0 | 本地推送通知 | | url_launcher | ^6.3.2 | 打开外部URL/应用 | | app_links | ^7.0.0 | 深度链接处理 | | home_widget | ^0.9.1 | iOS/Android桌面小组件 | | file_picker | ^8.3.7 | 文件选择器 | | image_picker | ^1.2.2 | 相机/相册选图 | | share_plus | ^13.1.0 | 系统分享面板 | | gal | ^2.3.0 | 保存图片/视频到相册 | | pro_image_editor | ^12.4.4 | 图片编辑器核心 | | flutter_quill | ^11.5.0 | Quill富文本编辑器 | | flex_color_picker | ^3.8.0 | HSL颜色选择器 | | flutter_image_compress | ^2.4.0 | 图片压缩 | | wakelock_plus | ^1.4.0 | 屏幕常亮控制 | | audioplayers | ^6.5.0 | 音频播放 | | record | ^6.0.0 | 录音 | | video_compress | ^3.1.2 | 视频压缩 | | video_player | ^2.10.0 | 视频播放 | | local_auth | ^3.0.1 | 生物识别认证 | | sensors_plus | ^6.1.0 | 加速度传感器 | | battery_plus | ^7.0.0 | 电池状态监听 | | network_info_plus | ^8.1.0 | WiFi网络信息 | | flutter_webrtc | ^1.4.0 | WebRTC音视频通信 | | flutter_blue_plus | ^2.1.0 | 蓝牙BLE通信 | | flutter_nfc_kit | ^3.6.0 | NFC读写 | | mobile_scanner | ^7.1.4 | 二维码/条形码扫描 | | wifi_iot | ^0.3.19 | WiFi IoT设备连接 | | nearby_service | ^0.2.1 | 近场设备发现+通信 | | sqflite | ^2.4.1 | SQLite轻量数据库 | | receive_sharing_intent | ^1.8.1 | 接收外部分享内容 | #### 2.2.2 dependency_overrides 区域 — 整体替换 MacBook Pro 端不需要 `dependency_overrides` 中的本地包覆盖,改为仅保留版本号覆盖: ```yaml # MacBook Pro 端的 dependency_overrides(精简版) dependency_overrides: meta: ^1.17.0 web: ^1.1.0 # 删除所有 path: packages/xxx 条目 ``` #### 2.2.3 快速替换脚本 ```bash # 在项目根目录执行,自动将本地包引用替换为远程版本 # ⚠️ 执行前请备份 pubspec.yaml # 方式1:手动替换(推荐,更可控) # 用编辑器打开 pubspec.yaml,搜索 "path: packages/" 逐个替换 # 方式2:使用 sed 批量替换(macOS 终端) # 将所有 "path: packages/xxx" 行替换为对应版本号 # 注意:此脚本仅作参考,请根据实际版本号调整 ``` #### 2.2.4 ⚠️ 重要:不要提交修改后的 pubspec.yaml ```bash # 修改 pubspec.yaml 后,使用 git stash 暂存,不要提交 git stash push -m "macOS-local-pubspec" pubspec.yaml # 需要恢复时 git stash pop # 或者将修改后的 pubspec.yaml 加入 .git/info/exclude echo "pubspec.yaml" >> .git/info/exclude ``` > **铁律**:MacBook Pro 端对 `pubspec.yaml` 的修改**绝对不能提交到 Git**。 > 仓库中的 `pubspec.yaml` 必须保持鸿蒙端的本地包引用配置。 ### 2.3 已迁移至远程版本的纯Dart包 以下包已从本地包迁移为远程版本依赖,两端无需额外操作: ``` badges ^3.2.0 | catcher_2 ^2.1.9 | flutter_card_swiper ^7.2.0 stupid_simple_sheet ^0.9.1+1 | liquid_glass_easy ^1.1.1 liquid_glass_widgets ^0.11.0 | flutter_shaders_ui ^0.1.0 flutter_spritesheet_animation ^1.0.1 | image_size_getter ^2.4.1 extended_image ^10.0.1 | photo_view ^0.15.0 ``` ### 2.4 MacBook Pro 端完整操作流程 ```bash # 1. 克隆仓库 git clone <仓库URL> xianyan cd xianyan # 2. 修改 pubspec.yaml(替换本地包为远程版本) # 参见 §2.2 的替换清单 # 3. 获取依赖 flutter pub get # 4. 编译验证 flutter build ios --no-codesign flutter build macos # 5. 防止误提交 pubspec.yaml git stash push -m "macOS-local-pubspec" pubspec.yaml # 或 echo "pubspec.yaml" >> .git/info/exclude ``` --- ## 三、Git 提交与合并规范 ### 3.1 分支策略 ``` main (受保护) ← 所有平台共用 ├── feature/xxx ← 功能开发(所有平台共用) ├── fix/xxx ← Bug修复 └── hotfix/xxx ← 紧急修复 ``` > **不需要按平台创建长期分支**。`lib/` 代码所有平台共用,独立平台分支会导致大量合并冲突。 > 平台原生代码已天然隔离(`ios/`、`macos/`、`ohos/` 各自独立),不会互相污染。 ### 3.2 iOS/macOS 开发者提交规则 **✅ 应该提交的文件:** - `lib/` 目录下的所有 Dart 代码 - `ios/` 目录下的原生代码 - `macos/` 目录下的原生代码 - `assets/` 目录下的资源文件 - `test/` 目录下的测试代码 **❌ 不要提交的文件:** - `pubspec.yaml`(MacBook Pro 端已替换为远程版本,**绝不能提交**) - `packages/` 目录(已在 `.gitignore` 中排除) - `ohos/` 目录下的鸿蒙原生代码 - 鸿蒙SDK特有的配置文件 **⚠️ pubspec.yaml 提交铁律:** 1. **MacBook Pro 端修改的 `pubspec.yaml` 绝对不能提交** — 仓库中的版本必须保持鸿蒙端本地包引用 2. **使用 `git stash` 或 `.git/info/exclude` 隔离修改** — 防止误提交 3. **如果必须提交 `pubspec.yaml`**(如新增了远程依赖),先 `git stash pop` 恢复原始版本,在原始版本上修改,再提交 ### 3.3 pubspec.yaml 处理策略(⭐ 重点) 由于 MacBook Pro 端和鸿蒙端使用不同的 `pubspec.yaml` 配置,需要特别注意。 #### 3.3.1 两端 pubspec.yaml 差异 | 区域 | 鸿蒙端(仓库版本) | MacBook Pro 端(本地版本) | |---|---|---| | dependencies 中的本地包 | `path: packages/xxx` | 远程版本号(如 `^2.5.5`) | | dependency_overrides | 包含所有 `path: packages/xxx` | 仅保留 `meta`、`web` 等版本号覆盖 | #### 3.3.2 MacBook Pro 端日常操作 ```bash # 开发前:恢复 MacBook Pro 本地版本 git stash list # 查看暂存 git stash pop # 恢复修改后的 pubspec.yaml # 开发中:正常编码,不涉及 pubspec.yaml 的提交 # 提交代码时:先暂存本地 pubspec.yaml git stash push -m "macOS-local-pubspec" pubspec.yaml git add lib/ ios/ macos/ assets/ git commit -m "feat: xxx" git push origin feature/xxx # 提交后:恢复本地 pubspec.yaml git stash pop ``` #### 3.3.3 需要新增依赖时 MacBook Pro 端新增依赖时,需要在**两端**分别操作: ```bash # ── MacBook Pro 端 ── # 1. 在本地 pubspec.yaml 中添加新依赖 echo " new_package: ^1.0.0" >> pubspec.yaml flutter pub get # 2. 恢复仓库版本的 pubspec.yaml git stash push -m "macOS-local-pubspec" pubspec.yaml git stash pop # 如果之前有暂存,先恢复 # 3. 在仓库版本的 pubspec.yaml 中也添加新依赖 # (保持鸿蒙端的本地包引用格式) # 4. 提交仓库版本 git add pubspec.yaml git commit -m "feat: add new_package dependency" # ── 通知鸿蒙开发者 ── # 告知新增了 new_package,评估是否需要鸿蒙适配 # 如果需要适配 → 鸿蒙端添加本地包引用 # 如果不需要适配 → 两端都使用远程版本 ``` #### 3.3.4 git pull 后 pubspec.yaml 被覆盖 ```bash # git pull 后,仓库版本的 pubspec.yaml 覆盖了本地修改 # 重新替换为远程版本即可: # 方式1:从备份恢复 git stash pop # 如果之前有暂存 # 方式2:重新手动替换(参见 §2.2) # 搜索 "path: packages/" 逐个替换为远程版本号 ``` #### 3.3.5 减少冲突的最佳实践 | 做法 | 说明 | |---|---| | **MacBook Pro 端不提交 pubspec.yaml** | 从根本上避免冲突 | | **使用 git stash 隔离** | 每次提交前 stash,提交后 pop | | **新增依赖时通知鸿蒙开发者** | 让鸿蒙端同步评估适配 | | **版本号升级单独提交** | 不要和功能代码混在一起提交 | ### 3.4 其他合并注意事项 1. **不要删除 `pu.isOhos` 相关代码**:这些条件分支在 iOS/macOS 上不会执行,但删除会导致鸿蒙端编译失败 2. **不要修改 `OhosAppShell`、`OhosNavBridge` 等鸿蒙专用类**:这些类仅在鸿蒙端使用 3. **新增页面路由时**:需同时在 `app_router.dart`(GoRouter路由表)和 `ohos_nav_bridge.dart`(鸿蒙路由映射表)中注册 ### 3.5 PR 审查要点 - [ ] 未提交 MacBook Pro 端修改的 `pubspec.yaml`(仓库版本保持鸿蒙本地包引用) - [ ] 未引入 `TargetPlatform` exhaustive switch 问题 - [ ] 新增路由已在 `ohos_nav_bridge.dart` 中同步 - [ ] `lib/` 代码无平台特定硬编码(应使用 `platform_utils.dart`) - [ ] 新增依赖已通知鸿蒙开发者评估适配 --- ## 四、TargetPlatform.ohos 处理 ### 4.1 问题背景 鸿蒙定制 Flutter SDK 在 `TargetPlatform` 枚举中新增了 `TargetPlatform.ohos`。 官方 SDK 不包含此值。本地包中引用了 `TargetPlatform.ohos`,在官方 SDK 下会编译报错。 **MacBook Pro 端的解决方案**:使用远程版本的三方库,远程版本不含 `TargetPlatform.ohos`,无需关心此问题。 ### 4.2 lib/ 代码中的平台判断 `lib/` 目录下的项目代码使用 `platform_utils.dart` 进行平台判断,**不依赖 `TargetPlatform.ohos` 枚举**, 在官方 SDK 下编译完全正常: ```dart // lib/ 代码使用 Platform.operatingSystem 字符串比较,不依赖枚举 // platform_io_native.dart: bool _isOhos() { try { return Platform.operatingSystem == 'ohos'; // 字符串比较,官方SDK也支持 } catch (_) { return false; } } ``` ### 4.3 iOS/macOS 开发者规范 **规则1:不要使用 `switch(TargetPlatform)` 穷举匹配** ```dart // ❌ 错误 — 官方SDK没有 ohos,鸿蒙SDK缺少 ohos 会报错 switch (defaultTargetPlatform) { case TargetPlatform.iOS: // ... case TargetPlatform.android: // ... case TargetPlatform.macOS: // ... case TargetPlatform.windows: // ... case TargetPlatform.linux: // ... case TargetPlatform.fuchsia: // ... } // ✅ 正确 — 使用 if-else 或添加 default if (defaultTargetPlatform == TargetPlatform.iOS) { // iOS 逻辑 } else if (defaultTargetPlatform == TargetPlatform.macOS) { // macOS 逻辑 } else { // 其他平台 } // ✅ 正确 — switch 加 default switch (defaultTargetPlatform) { case TargetPlatform.iOS: case TargetPlatform.android: return mobileLayout; default: return desktopLayout; } ``` **规则2:使用 `platform_utils.dart` 判断平台** ```dart import 'package:xianyan/core/utils/platform_utils.dart' as pu; // ✅ 推荐方式 — 内部使用字符串比较,两端都安全 if (pu.isIOS) { /* iOS */ } if (pu.isMacOS) { /* macOS */ } if (pu.isOhos) { /* 鸿蒙 */ } if (pu.isMobile) { /* 移动端 */ } if (pu.isDesktop) { /* 桌面端 */ } ``` ### 4.4 已知的 TargetPlatform.ohos 适配点(仅本地包) 以下文件在本地包中引用了 `TargetPlatform.ohos`,MacBook Pro 端使用远程版本不受影响: | 文件 | 位置 | 引用类型 | |---|---|---| | `packages/flex_color_picker/.../picker_functions.dart` | L49, L65 | `case TargetPlatform.ohos:` | | `packages/flutter_quill/.../raw_editor_state.dart` | L309 | `case TargetPlatform.ohos:` | | `packages/flutter_quill/.../link.dart` | L58 | `case TargetPlatform.ohos:` | | `packages/flutter_local_notifications/.../plugin.dart` | 8处 | `== TargetPlatform.ohos` | | `packages/mobile_scanner/.../method_channel.dart` | 3处 | `== / != TargetPlatform.ohos` | | `packages/audioplayers/.../audioplayer.dart` | L178 | `!= TargetPlatform.ohos` | > 以上文件均在 `packages/` 目录中,MacBook Pro 端使用远程版本,不会编译这些文件。 --- ## 五、其他注意事项 ### 5.1 应用入口架构差异 项目在 `app.dart` 中根据平台选择不同的应用架构: | 平台 | 应用架构 | 导航方式 | 入口Widget | |---|---|---|---| | iOS/macOS/Android | `MaterialApp.router` + GoRouter | GoRouter 声明式路由 | `AppShell` | | 鸿蒙 | `MaterialApp(home:)` + Navigator | `CupertinoTabView` + Navigator.push | `OhosAppShell` | **原因**:鸿蒙端 `MaterialApp.router` 白屏,无法使用 GoRouter,因此使用传统 Navigator 导航。 ### 5.2 路由注册双写 新增页面时,必须在两处注册路由: 1. **`lib/core/router/app_router.dart`** — GoRouter 路由表(iOS/macOS/Android 使用) 2. **`lib/core/router/ohos_nav_bridge.dart`** — 鸿蒙路由映射表 ```dart // app_router.dart GoRoute( path: AppRoutes.newPage, name: 'new-page', parentNavigatorKey: rootNavigatorKey, pageBuilder: (context, state) => iosSlideTransition(state: state, child: const NewPage()), ), // ohos_nav_bridge.dart AppRoutes.newPage: (_) => const NewPage(), ``` ### 5.3 平台特性检测 使用 `OhosDeviceCapabilities` 检测鸿蒙设备特性(毛玻璃、液态玻璃、重度动画、折叠屏等), iOS/macOS 端这些检测不会执行(`isOhos` 为 false),无需关心。 ### 5.4 packages 目录说明 - `packages/` 目录存放鸿蒙适配的本地三方库,已在 `.gitignore` 中排除 - **MacBook Pro 端不需要 `packages/` 目录**,直接使用远程版本即可 - 鸿蒙开发者需手动维护本地 `packages/` 目录 ### 5.5 MacBook Pro 修改 ios/macos 后,鸿蒙端是否需要同步? | 修改内容 | 鸿蒙端是否需要同步 | 原因 | |---|---|---| | `ios/` 目录 | ❌ 不需要 | 平台原生代码,鸿蒙不使用 | | `macos/` 目录 | ❌ 不需要 | 平台原生代码,鸿蒙不使用 | | `lib/` 目录 | ✅ 需要同步 | Dart 代码所有平台共用 | | `pubspec.yaml` | ✅ 需要同步 | 依赖配置共享(鸿蒙端自行维护本地包版本) | | `assets/` 目录 | ✅ 需要同步 | 资源文件共享 | ### 5.6 常见问题 | 问题 | 原因 | 解决方案 | |---|---|---| | `flutter pub get` 报 packages/xxx 目录不存在 | pubspec.yaml 中有 `path: packages/xxx` 引用 | 替换为远程版本号,参见 §2.2 | | 编译报 `TargetPlatform.ohos` 不存在 | 使用了含 ohos 引用的本地包 | 使用远程版本,参见 §2.1 | | iOS 编译报 ohos 相关错误 | 误用鸿蒙SDK编译iOS | 切换到官方 Flutter SDK | | GoRouter 路由正常但鸿蒙端白屏 | 鸿蒙端不支持 GoRouter | 检查 OhosNavBridge 路由映射 | | git pull 后 pubspec.yaml 被覆盖 | 仓库版本是鸿蒙端配置 | 重新替换为远程版本,参见 §3.3.4 | | 误提交了 MacBook Pro 端的 pubspec.yaml | 删除了鸿蒙本地包引用 | 立即回退,恢复鸿蒙端配置 | | 新增依赖后鸿蒙端报错 | 新增的三方库未适配鸿蒙 | 通知鸿蒙开发者评估,必要时本地化到 packages/ | --- ## 六、快速检查清单 MacBook Pro 开发前,确认以下事项: - [ ] 使用官方 Flutter SDK(非 flutter-ohos) - [ ] 已 `git clone` 拉取最新代码 - [ ] 已将 `pubspec.yaml` 中的本地包替换为远程版本(参见 §2.2) - [ ] `flutter pub get` 无报错 - [ ] `flutter build ios --no-codesign` 或 `flutter build macos` 编译通过 - [ ] 新增代码未使用 `switch(TargetPlatform)` 穷举匹配 - [ ] 新增路由已在 `app_router.dart` 和 `ohos_nav_bridge.dart` 双写 - [ ] 已使用 `git stash` 隔离本地 `pubspec.yaml`,不会误提交 - [ ] Git 提交未删除 `pu.isOhos` 相关代码 --- *文档创建时间: 2026-05-21 | 更新时间: 2026-05-21 v2 | 维护者: 闲言APP开发团队*