6.2 KiB
6.2 KiB
name, description
| name | description |
|---|---|
| daoqi-lessons | 从原项目 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 机制)
- 发现 1:Info.plist 用的是顶层无后缀的
- 原项目为什么稳:
- 它的所有 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 PNG(
- 不能照搬到新项目:
- LaunchImage Asset Catalog 在 iOS 14+ 已 deprecated,新项目按苹果推荐用
LaunchScreen.storyboard - LaunchScreen.storyboard 没有自动旋转 portrait 资源的魔法,UIImageView 直接渲染 PNG 物理像素
- 把
docs/res/Res/Default-568h@2x这类物理 portrait + 画面横躺的 msext 残留素材直接塞进 LaunchScreen.storyboard 就会看到躺倒画面
- LaunchImage Asset Catalog 在 iOS 14+ 已 deprecated,新项目按苹果推荐用
- 新项目(LaunchScreen.storyboard)的正确组合:
- 素材必须物理像素就是横屏的(必要时用
sips -r -90 -s format png一次性把 msext 残留 portrait 素材逆时针 90° 输出为标准 PNG,物理像素正确) - Info.plist 显式补一份无后缀
UISupportedInterfaceOrientations = landscape(Xcode 26 General → Deployment Info UI 只写带后缀的~iphone/~ipad,少了无后缀 key 会让 LaunchScreen 阶段——device idiom 尚未识别的早期窗口——fallback 到 portrait 渲染再被旋转) - UIImageView
contentMode = scaleAspectFit+ 黑底(比 16:9 更宽的现代横屏设备左右补黑边,保画面完整不裁切 logo)
- 素材必须物理像素就是横屏的(必要时用
- iOS launch snapshot 缓存粘滞(开发期 iteration 坑):
- iOS 为加速启动,会把首次渲染的 LaunchScreen 缓存为 PNG snapshot 存到 app sandbox(
Library/Caches/Snapshots/<bundleID>/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 <bundleID> - 终端用户不受影响:从 IPA 首次安装、或升级新 IPA 第一次启动后即被 iOS 自动刷新;只是开发期反复迭代同一台 device 时会被迷惑
- iOS 为加速启动,会把首次渲染的 LaunchScreen 缓存为 PNG snapshot 存到 app sandbox(
典型案例: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 业务用<script src="app_data.js">同步引入预生成的 12 个全局变量直接读 - 发现 2:Contract §附录 A 自身标注「iOS<9 路径使用的旧协议,新外壳如最低系统 ≥ iOS 14 可不实现」,新项目最低 iOS 15.6 → 旧桥 polyfill 完全不必要
- 发现 3:Contract §4.2 之前列的 11 项变量与原项目代码不一致 — 漏 6 项(version / Launchtype / getwifisignalLevel / gamename / invitationcode / gamesname)、多 2 项(gameid / compareCode 原项目根本不写)、文件名与变量名混淆(文件
app_battery.js内的变量名是带 get 的app_getbattery,文件名不带 get)
- 发现 1:原项目
- 修复:
- 撤销已实现的
window.settings.getXxx()polyfill 章节(Design §3.4.1) - 新增 Design §7.5「H5
app_*.js预注入文件机制」覆盖 15 个变量的写入逻辑 - 按原项目代码全面修订 Contract §4.2(删 gameid/compareCode、补 6 项、修正 battery/network 变量名带 get、注明大厅/子游戏字面差异、加修订记录小节)
- 撤销已实现的
- 教训:
- 文档与代码冲突时,原项目代码是真理。Contract 也可能写错(一份 10 年前写就的文档遗漏 / 误传是常态),必须用
grep验证字面字符串 - 优先验证字面字符串、不要依赖语义猜测:
app_getbattery与app_battery一字之差,AI 助手凭语义"应该就是 app_battery 吧" 100% 会犯错 - iOS 最低系统版本是契约边界的天然过滤器:契约里 iOS<9 路径明示可不实现的接口(如 §附录 A 旧桥),新项目最低 iOS 15.6 应当主动剔除,不要"出于完备性"反而实现一份用不到的 polyfill
- 文档与代码冲突时,原项目代码是真理。Contract 也可能写错(一份 10 年前写就的文档遗漏 / 误传是常态),必须用