diff --git a/.claude/skills/daoqi-lessons/SKILL.md b/.claude/skills/daoqi-lessons/SKILL.md new file mode 100644 index 0000000..f397156 --- /dev/null +++ b/.claude/skills/daoqi-lessons/SKILL.md @@ -0,0 +1,51 @@ +--- +name: daoqi-lessons +description: 从原项目 daoqi/msext 排查出来的典型案例存档(LaunchScreen 启动图方向错误、H5 与原生通讯接口的真实路径)。在处理启动图 / LaunchScreen / 启动方向问题,或处理 H5 读取渠道值、app_*.js 变量、window.settings polyfill 相关问题时阅读。 +--- + +# 原项目 daoqi 排查案例存档 + +> 这些是从 `../daoqi/` 实际排查出来的完整案例,佐证 CLAUDE.md「原项目 daoqi:遇到问题时的参考来源」一节的方法论。 +> 注意:`典型案例:app_* 注入时序问题(原则 A 不可妥协)` 仍保留在 CLAUDE.md 正文中,因为它是原则 A 的规范性说明,必须常驻。 + +## 典型案例:LaunchScreen orientation(启动图方向错误) + +- **症状**:新项目启动图渲染成竖向矩形再被整体旋转 90°,画面横躺在中间 +- **错误做法**:凭 Xcode 26 文档推测、纯调整 storyboard / contentMode / 反复换素材 +- **去原项目找答案**:`daoqi/msext/Info.plist` + `msext.xcodeproj/project.pbxproj` + - 发现 1:Info.plist 用的是**顶层无后缀的 `UISupportedInterfaceOrientations`**(值 = landscape),**没有** `~iphone` / `~ipad` 后缀变体 + - 发现 2:根本**没有** `UILaunchStoryboardName`,用的是 `ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = "LaunchImage-1"`(iOS 8 时代的 LaunchImage Asset Catalog 机制) +- **原项目为什么稳**: + - 它的所有 LaunchImage PNG(`Default-568h@2x` / `LaunchImage-1-800-667h@2x` 等)**物理像素都是竖向、画面内容横躺** + - iOS 8 LaunchImage Asset Catalog 内置"按 device idiom + orientation 自动选图 + 系统级 90° 旋转"魔法,会读 Info.plist 顶层 `UISupportedInterfaceOrientations` 决定是否旋转 portrait 资源 + - 因此一张物理 portrait 的 PNG 在横屏设备上能被正确旋转后铺满 +- **不能照搬到新项目**: + - LaunchImage Asset Catalog 在 iOS 14+ 已 deprecated,新项目按苹果推荐用 `LaunchScreen.storyboard` + - LaunchScreen.storyboard **没有自动旋转 portrait 资源**的魔法,UIImageView 直接渲染 PNG 物理像素 + - 把 `docs/res/Res/Default-568h@2x` 这类**物理 portrait + 画面横躺**的 msext 残留素材直接塞进 LaunchScreen.storyboard 就会看到躺倒画面 +- **新项目(LaunchScreen.storyboard)的正确组合**: + 1. **素材必须物理像素就是横屏的**(必要时用 `sips -r -90 -s format png` 一次性把 msext 残留 portrait 素材逆时针 90° 输出为标准 PNG,物理像素正确) + 2. **Info.plist 显式补一份无后缀 `UISupportedInterfaceOrientations = landscape`**(Xcode 26 General → Deployment Info UI 只写带后缀的 `~iphone` / `~ipad`,少了无后缀 key 会让 LaunchScreen 阶段——device idiom 尚未识别的早期窗口——fallback 到 portrait 渲染再被旋转) + 3. UIImageView `contentMode = scaleAspectFit` + 黑底(比 16:9 更宽的现代横屏设备左右补黑边,保画面完整不裁切 logo) +- **iOS launch snapshot 缓存粘滞(开发期 iteration 坑)**: + - iOS 为加速启动,会把首次渲染的 LaunchScreen 缓存为 PNG snapshot 存到 app sandbox(`Library/Caches/Snapshots//com.apple.UIKit.SplashBoard/`),后续启动不重渲染 + - **Xcode 覆盖安装 .app 不会清 sandbox 缓存**,所以改了 Info.plist / LaunchScreen.storyboard / 启动图素材后,Run 出来仍可能是旧 snapshot + - 改完启动相关任意一项**必须做**:长按 app → 删除 → Xcode 重新 Run;或模拟器 Erase All Content and Settings;或 `xcrun simctl uninstall booted ` + - **终端用户不受影响**:从 IPA 首次安装、或升级新 IPA 第一次启动后即被 iOS 自动刷新;只是开发期反复迭代同一台 device 时会被迷惑 + +## 典型案例:H5 与原生通讯接口的真实路径 + +- **症状**:Design / Contract 文档描述 H5 用 `window.settings.getXxx()` 同步函数读渠道值(如 `getothername` / `getchannelName`);按文档实现完 polyfill 后 H5 业务行为不对,user 反馈"H5 读不到数据" +- **错误做法**:基于 Contract §附录 A 列出的旧桥 JSExport 28 方法实现 polyfill,把 9 项 getter 注入到 `window.settings`,认为这是 H5 端的主路径 +- **去原项目找答案**:grep `var app_` 在 `daoqi/msext/Class/RootVC/NewRootVC.m:1204` / `gameController.m:2160` / `AppDelegate.m:259` + - 发现 1:原项目 `initJSdata()` 是 `[NSString stringWithFormat:@"var app_xxx=...;"]` + `writeToFile:` **写 .js 文件到沙盒**,H5 业务用 `