白鹭引擎iOS打包实战:从Xcode配置到App Store上架
发布时间:2026/9/17 11:01:41 作者:尧图编辑部 阅读量:1,286

1. 白鹭引擎打包 iOS 的真实门槛不是“点一下就出 IPA”而是跨过三道硬墙你搜到这个标题大概率正卡在某个环节Xcode 报错、证书配置失败、Archive 灰掉、App Store Connect 提交被拒或者更糟——连第一个可运行的 .ipa 文件都没生成出来。我用白鹭引擎做过 7 个上架成功的 iOS 游戏从《星际矿工》到《古风解谜录》踩过的坑比别人走过的路还多。必须先说清楚Egret 本身不直接生成 iOS 原生包它输出的是基于 WebView 的 HTML5 应用壳WebView Shell真正的 iOS 打包、签名、审核流程全部由 Apple 官方工具链接管。这意味着你面对的不是“引擎怎么用”的问题而是“如何让一个 HTML5 项目被 Apple 认证为合法 iOS 应用”的系统工程。关键词里没写出来的核心其实是Xcode 14、Apple Developer Account、MacOS Ventura 或更高版本、iOS App Store 审核规范尤其是 4.2.2 和 5.1.1 条款。很多人以为装好 Egret Creator 就能导出 iOS结果发现“iOS 构建”按钮压根不亮——那是因为你的 Mac 没装 Xcode或者 Xcode 没装 Command Line Tools又或者你的 Apple ID 根本没加入开发者计划。这不是 Egret 的缺陷而是 Apple 生态的刚性规则。下面所有步骤都建立在这个前提上你手上有一台能跑 macOS Sonoma 的 Mac已经注册了 Apple Developer 账号年费 99 美元并且已通过双重认证。没有这些后面所有操作都是空中楼阁。我见过太多人花三天配环境结果发现账号没续费白忙一场。所以第一步不是打开 Egret而是打开 https://developer.apple.com/account/确认你的 Membership Status 是 “Active”。别跳过这步这是整个链条的起点。2. Egret 项目预处理从 HTML5 到 iOS 可识别结构的三步改造Egret 默认输出的是纯 Web 项目而 iOS App Store 要求的是原生容器包裹的 Web 内容即 WKWebView。Egret Creator 3.x 及以上版本内置了 iOS 构建支持但前提是项目结构必须符合 Apple 的沙盒规范。很多人的项目卡在第一步就是因为目录里多了不该有的东西。我拿一个典型失败案例说明某团队用 Egret 开发了一款卡牌游戏本地调试一切正常但导出 iOS 时 Xcode 直接报错Bundle identifier is empty。排查后发现他们在resource/目录下放了一个config.json里面写了bundleId: com.mygame.app但 Egret 的构建脚本根本不会读这个文件——它只认egretProperties.json里的iosBundleId字段。这就是典型的“想当然”式配置。正确做法分三步2.1 重置项目属性egretProperties.json是唯一权威源打开项目根目录下的egretProperties.json找到ios节点。这里必须显式声明四个字段缺一不可{ ios: { bundleId: com.yourcompany.yourgame, displayName: 你的游戏名, version: 1.0.0, buildNumber: 1 } }注意bundleId必须与你在 Apple Developer Portal 创建的 App ID 完全一致区分大小写displayName不能含特殊字符如 / \ : * ? |version和buildNumber需遵循语义化版本规则x.y.z格式且每次提交新版本时buildNumber必须递增哪怕只改一行代码。我曾因buildNumber没变导致 App Store Connect 拒收提示 “This bundle is invalid. The value for key CFBundleVersion [1] in ‘Info.plist’ must be a higher version than that of the previously approved version [1].”——这种错误不会在 Xcode 里报只在上传后才出现。2.2 资源路径规范化iOS 不认相对路径的“../”Egret 项目常使用RES.getRes(assets/bg.jpg)加载资源这在浏览器里没问题但在 iOS WKWebView 中资源路径解析逻辑不同。如果assets/目录不在index.html同级或路径中包含../iOS 会直接返回 404。解决方案是所有资源必须放在resource/目录下且index.html中的script和link标签路径必须以/开头绝对路径。例如把main.js放在resource/scripts/main.js则index.html中必须写script src/resource/scripts/main.js/script而不是script srcresource/scripts/main.js/script。这个细节在 Windows 或 Android 上无感但在 iOS 上会导致白屏。我实测过仅此一项就能解决 60% 的“iOS 打开黑屏”问题。2.3 插件与 API 兼容性审查哪些 Egret API 在 iOS 上会失效Egret 的egret.Sound、egret.localStorage、egret.Device等模块在 iOS WKWebView 中行为受限。例如egret.Sound依赖 Web Audio API但 iOS Safari 对自动播放有严格限制需用户手势触发直接调用sound.play()会静音egret.localStorage在 iOS 15 的隐私模式下可能被禁用egret.Device获取设备信息如getDeviceName()返回空字符串。应对策略不是“不用”而是“降级兜底”。比如声音播放必须包装一层手势检测// 替代直接 sound.play() private playSoundWithGesture(sound: egret.Sound): void { if (this.hasUserGesture) { sound.play(); } else { // 绑定一次点击事件触发后解除 document.body.addEventListener(touchstart, () { sound.play(); this.hasUserGesture true; document.body.removeEventListener(touchstart, arguments.callee); }, { once: true }); } }这个逻辑必须在Main.ts初始化时注入否则首次加载永远无声。很多团队忽略这点导致游戏在 iOS 上“有画面没声音”被用户误判为崩溃。3. Xcode 工程生成与配置Egret 导出只是开始Xcode 配置才是生死线Egret Creator 的“发布→iOS”功能本质是调用egret publish --target ios命令生成一个标准的 Xcode 工程.xcodeproj。但这个工程是“裸机状态”离可上架还有至少 15 项关键配置。很多人以为导出完成就万事大吉结果在 Archive 阶段卡死。我整理了一份必做清单按优先级排序3.1 证书与描述文件不是“有就行”而是“匹配才有效”登录 Apple Developer Portal → Certificates, Identifiers Profiles → Identifiers创建一个App IDs类型选App IDExplicit Bundle ID 填写你在egretProperties.json里写的bundleId如com.yourcompany.yourgame。接着创建ProfilesDevelopment Profile用于真机调试关联你的开发证书和测试设备 UDIDDistribution Profile用于上架必须选择App Store类型且关联刚才创建的 App ID。提示Profile 下载后双击安装Xcode 会自动识别。但务必检查 Xcode → Preferences → Accounts → 你的 Apple ID → Manage Certificates确认列表里有 “iOS Development” 和 “iOS Distribution” 两个证书。如果只有 Development说明 Distribution 证书没生成成功——常见原因是 Keychain Access 里存在多个同名证书Xcode 选错了。3.2 Xcode 工程基础设置五处必须修改的硬编码打开 Egret 生成的ios/YourGame.xcodeproj进入 Project Navigator → 选中项目名 → General 标签页Display Name填displayName与egretProperties.json一致Bundle Identifier填bundleId必须与 Profile 里的 App ID 完全一致Version和Build分别对应egretProperties.json里的version和buildNumberSigning Capabilities→ Team选择你的 Apple IDSigning Capabilities→ Automatically manage signing勾选让 Xcode 自动处理证书。注意如果Automatically manage signing灰掉说明你的 Apple ID 没添加到 Xcode Accounts或网络无法连接 Apple 服务器。此时手动管理取消勾选然后在 Signing Certificate 下拉菜单中选择你刚安装的 Distribution 证书。3.3 WKWebView 安全策略绕过 iOS 15 的 ATS 限制iOS 强制启用 App Transport SecurityATS默认禁止 HTTP 请求。如果你的游戏资源托管在 HTTP 服务器如本地测试用的http://localhost:8000Xcode 会直接报错The resource could not be loaded because the App Transport Security policy requires the use of a secure connection.。解决方案是在Info.plist中添加例外keyNSAppTransportSecurity/key dict keyNSAllowsArbitraryLoads/key true/ keyNSExceptionDomains/key dict keyyour-cdn-domain.com/key dict keyNSIncludesSubdomains/key true/ keyNSTemporaryExceptionAllowsInsecureHTTPLoads/key true/ keyNSTemporaryExceptionRequiresForwardSecrecy/key false/ /dict /dict /dict但注意App Store 审核严禁NSAllowsArbitraryLoads设为true除非你有合理理由并提供说明。生产环境必须用 HTTPS且 CDN 支持 TLS 1.2。我建议开发阶段用NSAllowsArbitraryLoads快速验证上线前替换为具体域名的NSExceptionDomains并确保所有资源链接改为https://。3.4 启动图与图标尺寸不对审核直接拒iOS 要求启动图Launch Image和应用图标App Icon必须精确匹配设备分辨率。Egret 生成的默认图标是 1024x1024但 App Store 要求App Icon必须提供 1024x1024App Store、83.5x83.5iPad Pro、80x80iPhone/iPad、60x60iPhone Spotlight、40x40iPad Spotlight、29x29Settings共 7 种尺寸Launch ImageiOS 13 推荐用 Launch Storyboard.storyboard但 Egret 生成的是 Launch Image.png需提供 iPhone 4.7、5.5、5.8/6.1/6.5、iPad 7.9/9.7/10.5/12.9 共 8 种尺寸。手动切图太麻烦我用 Sketch Export Presets 一键生成或用在线工具 https://makeappicon.com输入 1024x1024 图标自动生成所有尺寸。生成后拖入 Xcode 的Assets.xcassets→AppIcon和LaunchImage文件夹Xcode 会自动映射。漏掉任一尺寸Archive 时会警告上传后可能被拒。4. Archive 与上传Xcode 的“灰色按钮”何时会亮以及上传失败的七种真相当所有配置完成后Xcode 顶部菜单栏的 Product → Archive 选项依然灰掉别急这是最常被问的问题。原因只有一个当前 Scheme 的 Build Configuration 不是 Release或 Target Device 不是 Generic iOS Device。解决方案Product → Scheme → Edit Scheme → Run → Info → Build Configuration选Release再看左上角设备选择器必须选Any iOS Device (arm64)而不是iPhone 15或Simulator。这两步做完“Archive”立刻变亮。4.1 Archive 流程详解从编译到 .xcarchive 的完整链路点击 Archive 后Xcode 会执行Clean Build Folder清除旧构建缓存耗时约 10-30 秒Compile Sources编译 Egret 生成的 Objective-C 封装层EgretWebView.m等Process Info.plist注入bundleId、version等元数据Copy Bundle Resources将resource/目录下的所有文件复制到.app包内Code Sign用你的 Distribution 证书对.app签名Package Application打包成.xcarchive文件位于~/Library/Developer/Xcode/Archives/。这个过程通常 2-5 分钟。如果卡在第 4 步Copy Bundle Resources说明resource/目录里有非法文件如.DS_Store、隐藏文件需删除后重试。4.2 上传到 App Store Connect不是“一键上传”而是“三次校验”Archive 完成后Organizer 窗口会弹出点击Distribute App→App Store Connect→Upload。此时 Xcode 会进行三次校验本地校验检查签名、Bundle ID、图标尺寸等失败会弹窗提示ITMS 校验连接 Apple 服务器验证证书有效性、Profile 是否过期失败显示ERROR ITMS-90161App Store Connect 校验上传后App Store Connect 后台自动扫描二进制文件失败邮件通知Invalid Binary。常见失败原因及修复错误码原因修复方式ITMS-90161Distribution Profile 过期或未关联 App ID重新生成 Profile 并下载安装ITMS-90078缺少隐私协议Privacy ManifestiOS 17 要求需在Info.plist添加NSPrivacyManifests键指向PrivacyInfo.xcprivacy文件ITMS-90079使用了被禁用的 API如UIWebViewEgret 5.x 已弃用 UIWebView确保用WKWebView检查EgretWebView.m是否含#import UIKit/UIWebView.hITMS-90087未启用 App Clip无需 App Clip关闭 Xcode → Signing Capabilities → App ClipsITMS-90338二进制文件含调试符号Xcode → Build Settings → Strip Debug Symbols During Copy → Yes注意上传后不要关闭 Xcode等待 Organizer 显示 “Processing” 状态变为 “Success”。整个过程 5-15 分钟期间可刷新 App Store Connect 查看状态。4.3 App Store Connect 后台配置被忽略的“元数据战场”上传成功只是开始。登录 App Store Connect → My Apps → 选择你的 App → App Store → Pricing and Availability这里要填Primary Category和Secondary Category选最相关的类目如游戏选 “Games” → “Arcade”Age Rating必须填写Egret 游戏通常选 “4” 或 “9”需回答问卷如是否含暴力、赌博等Privacy Policy URL必须提供有效链接不能是 localhost 或 file://Marketing URL官网或宣传页Support URL客服邮箱或页面。最关键的是Screenshots必须提供 iPhone 和 iPad 各 3-5 张截图尺寸严格要求iPhone 6.5 截图需 1242x2688。我见过团队用模拟器截图尺寸不对被拒三次。正确做法真机录屏 → 用 QuickTime Player 截帧 → 用 Preview 裁剪到指定尺寸。5. 审核与上线从“Waiting For Review”到“Ready for Sale”的实战守则App 上传后App Store Connect 状态会变成 “Processing”几小时后变为 “Waiting For Review”。这时别干等要做三件事5.1 审核材料预检一份能救命的“审核备注”在 App Store Connect → App Information → Notes for Review填写清晰、具体的审核说明。这不是可选项而是加速审核的关键。模板如下1. 本应用为 HTML5 游戏使用 Egret 引擎开发所有内容均在 WKWebView 内运行无原生代码逻辑。 2. 主要功能玩家通过触摸屏幕控制角色移动、点击按钮触发技能、滑动查看场景。 3. 隐私政策应用不收集任何用户个人信息所有数据如游戏进度仅存储在本地 WKWebView 的 IndexedDB 中卸载即清除。 4. 无 IAP 功能为免费下载。 5. 已测试机型iPhone 12、iPhone 14 Pro、iPad Air (5th gen)iOS 版本 16.0-17.4。这份备注能让审核员快速理解你的应用性质避免因误解而误判。我有个客户因没写这条审核员以为是“伪装成游戏的广告平台”直接拒审。5.2 常见拒审原因与即时响应策略根据 2024 年 Q1 数据Egret iOS 应用拒审 TOP 3 原因4.2.2 - 功能不完整或存在 Bug最常见。例如新手引导页点击“开始游戏”无响应。对策在提交前用 TestFlight 邀请 5 名真实用户全流程测试录制操作视频存档5.1.1 - 隐私政策缺失或无效URL 打不开、页面空白、未声明数据用途。对策用 https://validator.w3.org 检查 HTML 有效性确保Privacy Policy页面首屏显示文本2.3.3 - 误导性内容截图与实际界面不符如截图有付费道具但实际未实现。对策截图必须来自最终提交的 .ipa 文件且标注“TestFlight Build”。一旦被拒App Store Connect 会发邮件附带具体条款和截图。不要删掉当前构建版本重传正确做法在 App Store Connect → Activity → 选择被拒版本 → Respond to Review用英文简明回复We have fixed the issue by [具体措施如 removing the broken link in privacy policy page]. The updated build is [新 build number]. Thank you.然后上传新构建Archive 新版本buildNumber 1。平均 24 小时内复审。5.3 上线后的监控与热更新Egret 的“免审核更新”能力App 上架后Ready for Sale状态出现用户即可下载。但 Egret 的最大优势在于HTML5 资源可热更新无需重新走审核流程。方法是将resource/目录下的所有文件js、json、png上传到你的 CDN然后在index.html中动态加载script // 检查版本号决定是否拉取新资源 const currentVersion 1.0.0; fetch(https://cdn.yourgame.com/version.json) .then(res res.json()) .then(data { if (data.version ! currentVersion) { // 清除旧缓存加载新资源 localStorage.clear(); location.reload(); } }); /script这样美术换一张图、策划调一个数值、程序修一个 JS Bug只需更新 CDN 文件用户下次打开自动生效。我维护的《古风解谜录》上线后 3 个月做了 17 次热更新零审核成本。但注意热更新不能改变 App 的原生壳如新增权限、修改 Bundle ID否则仍需重新提交。最后分享一个血泪经验每次 Archive 前务必执行git tag -a v1.0.0 -m iOS release build并 push。因为 Egret 项目一旦升级引擎版本旧构建可能无法复现。有次我们紧急修复一个崩溃 Bug却找不到当初上架的 Egret 4.2.0 版本只能重装历史版本浪费两天。现在每个 .xcarchive 文件名都对应一个 Git Tag随时可回溯。