ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

iOS上架Invalid Binary排查指南:从错误码到修复全流程

iOS上架Invalid Binary排查指南:从错误码到修复全流程 晚上十一点多邮箱弹出一封标题只有两个词的邮件Invalid Binary。发件人是 App Store Connect。你点进去正文可能带着几行错误码也可能只有一句冷冰冰的 this bundle is invalid连个具体原因都不给。如果你这时候打开后台看到 Activities 里刚从 Processing 翻红的那条构建还杵在那儿那恭喜你提审前最容易让人失眠的坑被你赶上了。先说清楚一个认知无效二进制不是一个单一的技术错误它更像是苹果后台对上传包做了一系列静态检查之后给出的“不合格”结论。你本地能编译、能真机跑、能顺利 Archive都跟这个结论没有必然关系。本地工具链宽松后台检查严格这两者之间的落差就是大家集体踩坑的地方。这篇文章适合所有跟 iOS 上架流程打过交道的人独立开发者、App 负责人、维护 CI 打包脚本的工程师。只要你用的是正规的 Xcode Archive 产物下面这套排查方法基本能覆盖 90% 的 Invalid Binary 场景。如果是非官方工具生成、脱离 Xcode 流程的包那不在本文讨论范围内也建议你别拿去撞后台规则。1. 无效二进制的完整现场邮件、红状态与后台的检查机制1.1 大部分人是这样收到噩耗的方式通常有三种按“吓人程度”排序。最典型的是邮件。App Store Connect 会在构建状态变化后给你发一封通知标题就写 Invalid Binary发件人地址是 App Store Connect 系统邮箱。邮件正文不一定包含错误码有时候只有一句“The bundle is invalid”有时候会带上 ITMS 开头的编号比如 ITMS-90022、ITMS-90087 这种这些编号在后面会讲是定位问题的第一把钥匙。第二种方式是打开 App Store Connect进入“App - 活动”页面看到某条构建记录的状态从 Processing 变成红色旁边标注 Invalid Binary。这种情况通常邮件还没到或者邮件被扔进了垃圾箱。所以收到上传成功的提示之后别急着关浏览器盯一眼 Activities 的状态变化。第三种最隐蔽你是在提交审核的最后一刻才发现的。因为构建被标记为无效但旧版本还能用列表里根本选不到新的那个于是你才注意到后台已经在某个时间点悄悄把状态翻红了。我见过不少团队是在“马上要提审、老板来催”的时候才发现包早就红了所以这里先立一条规矩每次上传完等处理结束看到状态变为绿色的 Available 或 Processing 完成后再做其他事。别让后台在你看不见的时候做决定。1.2 App Store Connect 后台到底在看什么很多人不理解为什么 Xcode 上传时不报错后台却给你个无效二进制。原因是 Xcode 在上传阶段只做两件事校验基础的签名和包结构然后把文件传上去。苹果接收之后后台会执行一套更深的静态检查包括但不限于Mach-O 可执行文件的架构是否合法有没有混入模拟器架构或未知架构Info.plist 里的关键字段是否齐全、格式是否正确比如 CFBundleVersion、CFBundleShortVersionString、Bundle IDApp 图标是否存在尺寸是否满足是否带透明通道是否访问了需要权限声明的隐私接口而对应的 UsageDescription 缺失或为空是否引用了某些已废弃的 API导出合规、加密声明、扩展目标的配置是否合理。这些检查全是静态的它不会真去运行你的 App。也就是说你的 App 在真机上跑得再欢也不影响这些规则判定你“无效”。这也解释了为什么很多问题在开发阶段完全暴露不了——开发时你根本不会走这一套流程。我之前跟团队小伙伴打过一个比方Xcode 上传就是进停车场保安只拦明显没挂牌的车后台的静态检查才是验车线发动机号、车架号、灯光、刹车全部过一遍才算合格。你平时在小区里开得再顺手上验车线该亮红灯还是亮红灯。1.3 两个容易误判的细节Processing 时间与构建号复用第一个细节是关于 Processing 的等待时间。上传成功之后后台处理通常需要几分钟到几十分钟高峰期甚至更久。很多人一看到 Processing 状态超过十分钟就慌反复重新上传同一个包结果反而可能收到“构建号重复”或“已有版本号”这类新错误。我的建议是只要不是超过两小时还没变化就不要动它。处理时间长短不代表成功或失败等到状态落定再说。第二个细节比时间更隐蔽一旦某个构建被判定为 Invalid Binary它不会消失后台会把它保留在活动列表里但它永远无法被选中提交。你想修复问题不能重传同一个构建号必须重新归档、让 Build 号递增、再传一个新包。换句话说你手上那个有问题的包已经“死”了抢救的意义不大直接准备下一个。搞清楚这个底层逻辑之后再看具体的报错就开始有方向感了。2. 先对号入座ITMS-90000 系列错误码的真实含义与处理动作2.1 版本号/构建号ITMS-90060、90061、90473这三个错误码都跟版本信息相关含义非常接近很多人容易搞混我拆开说。ITMS-90060 说的是 CFBundleVersion也就是 Build 号必须高于之前上传过的版本。苹果后台每收到一个上传包都会记录这个构建号。你修改完代码再次上传时如果 Build 号没变或者比之前传过的低就会触发这个错误。很多小团队用日期做构建号比如 2024.06.01如果同一天补传多次且忘记更新很容易撞车。ITMS-90061 针对的是 CFBundleShortVersionString也就是展示给用户的版本号。后台要求它必须高于之前提交过的版本。这里有个特别容易翻车的地方版本号比较不是简单的字符串比较也不是整数比较而是一段一段做数字比较。举例来说2.10.0 大于 2.9.9因为第二段 10 大于 9。如果你发过 2.10.0下一次想发 2.9.1哪怕你觉得“9 比 10 小我是降级修复”后台也会直接拒绝。ITMS-90473 说的是版本号格式。后台要求短版本号必须符合 x.y 或 x.y.z 的格式每段只能包含数字和点号。如果你填了 1.0.0-beta、2.0.0 (fix) 这类带字母或空格的字符串就会收到这个错误。顺带提醒提交前在 Xcode 的 General 标签页里看一下 Version 和 Build 两个字段确保都是纯数字加点的格式。处理这三个错误码的动作很一致把版本号和构建号改成满足条件的值Clean 之后重新 Archive。改完之后在项目的 Info.plist 里确认这两个键的值真的变了。有些时候你改了 UI 里的字段但归档用的 target 没选对最后打出来的包还是旧值这种情况并不少见。2.2 图标ITMS-90022 与 90023图标类错误在 Invalid Binary 里占比极高因为很多人对图标的要求理解只停留在“看起来是张图”的层面。ITMS-90022 的意思是缺少必需的图标文件最常见的是缺失 1024x1024 的 App Store 图标。如果你用的还是老式的非 Asset Catalog 图标准备方式或者 Assets.xcassets 里的 AppIcon 没有把 1024 那一格拖进去上传后大概率踩中这个错。ITMS-90023 说明图标里带了 alpha 通道。苹果在大多数平台要求 App 图标不允许包含透明通道但很多设计工具导出 PNG 时默认会保留透明信息。哪怕你看到的图片是纯白底只要文件的 alpha 通道有信息就会被判定为不合格。这里建议图像处理不熟的朋友直接用命令验证打开终端进入图标所在目录执行sips -g hasAlpha icon.png如果输出hasAlpha: yes就必须去掉透明通道再重新导出。处理方案分两种最稳妥的是让设计从源文件重新导出导出时明确选择“不包含透明度”临时救急的话可以用脚本把透明区域铺成白色底我后面会给一个可复用的 Python 写法。资产文件不要手工猜用命令验证完再放入 Asset Catalog能省掉来回上传的折腾。2.3 架构ITMS-90087 与 90125这两个错误码都指向同一个问题包里存在后台不允许的架构。正常情况下一个面向 iOS 真机的 Archive 包应该只包含 arm 系列架构现在主流是 arm64。但当你集成了一些预编译的第三方静态库、framework或者 CI 机器上打包时没有切对目标设备很容易把 i386 或 x86_64 这种模拟器架构一起打进去。上传之后后台一解析 Mach-O 文件发现不该出现的架构直接给你标成无效。排查方式很简单把 Archive 导出成 ipa解压出 App 里的主可执行文件执行lipo -info看一下支持的架构列表。我用一个例子说明lipo -info /path/to/YourApp.app/YourApp输出里如果出现x86_64或i386那就别急着传第二次先把架构问题解决掉。解决思路通常是确认 Archive 的时候目标设备选的是“Any iOS Device (arm64)”而不是模拟器检查所有第三方 framework 的 Release 版本是否只包含真机架构如果还不行可以在 Build Phase 里加一段脚本在打包时把模拟器架构删掉。具体脚本在后面案例部分会写。2.4 权限声明ITMS-90683iOS 10 之后系统对隐私数据的访问要求必须在 Info.plist 里声明用途描述。相册、相机、定位、麦克风、通讯录、日历、蓝牙、健康数据这些都有对应的 NS*UsageDescription 键。如果你在代码里调用了相关接口但 Info.plist 里没有对应的键或者键的值是空字符串后台在静态检查阶段就可能直接判定无效错误码常见是 ITMS-90683。这个问题的隐蔽之处在于本地开发时模拟器或真机首次弹窗会显示你声明的描述如果你压根没声明系统可能不会崩溃只是不弹窗或直接崩溃并没有统一的前置报错很多团队因此一直没发现。直到提审那一步才被后台揪出来。处理方式是逐项核对 Info.plist 里的权限键。我习惯拉一个清单把 App 用到的隐私接口全部列出来对照 Info.plist 检查键是否存在、值是否非空、拼写是否精确正确。注意这些键名必须一字不差比如NSCameraUsageDescription少写一个字母后台认不出来等于没写。2.5 其他常见错误码速查表除了上面几类还有一批出现频率不低的报错我把它们整理成一张速查表方便你收到邮件后快速对号入座。错误提示真实含义最快处理ITMS-90022 Missing required icon fileApp 图标缺失或尺寸不满足检查 AppIcon补全各尺寸重点确认 1024 图标ITMS-90023 Invalid Icon ... alpha channel图标带透明通道去掉 alpha重新导出 PNGITMS-90060 CFBundleVersion must be higher构建号没有高于上一次增大 Build 号重新 ArchiveITMS-90061 CFBundleShortVersionString must be higher版本号低于已提交过的版本使用单调递增的版本号ITMS-90087 / 90125 unsupported/invalid architecture包含模拟器架构或非法架构lipo 检查并排除 i386/x86_64ITMS-90683 Missing Info.plist key隐私权限未声明或声明为空补全并核对 UsageDescriptionITMS-90809 Deprecated API usage使用了已废弃的 UIWebView迁移到 WKWebView 后重新打包Invalid Bundle Structure包内缺少可执行文件或关键目录结构不对用 Xcode Archive 重新导出不要手动改包内容还有一类邮件正文不带错误码只有一句 “This bundle is invalid.” 后面括号里可能写着更详细的描述。如果描述里提到 missing the bundle identifier 或 does not contain a bundle executable先别怀疑证书回 Xcode 里确认 Archive 导出的是“App Store Connect”分发方式而不是 Ad Hoc 或 Development。3. 没有错误码时按这份隐性原因清单逐项排查3.1 邮件只有一个 Invalid Binary 时先看 Activity 详情如果邮件正文真的只有一个光秃秃的 Invalid Binary第一步不是去改代码而是回到 App Store Connect 的“活动”页面点开那条红色构建记录看看有没有补充信息。有些情况下后台会把更详细的错误写在构建详情里只是没进邮件。这个地方经常被人忽略我见过有人翻遍邮箱没找到原因结果详情页里清清楚楚写着缺哪个图标。另外可以看上传工具。如果你用的是 Xcode Organizer 或 Transporter上传日志里可能会留存一些验证阶段的警告这些警告虽然不会阻止上传但往往是后台判定无效的预兆。比如日志里出现 “beta” 字样、传感器/辅助框架警告、某个文件路径异常都值得多看一眼。3.2 隐性原因一大小写敏感的资源引用很多 Invalid Binary 查到最后根因是资源文件引用的大小写问题但这个原因特别隐蔽。macOS 的默认文件系统不区分大小写所以你在本地开发时代码里引用图片资源写成[UIImage imageNamed:LaunchLogo]而实际文件名是launchlogo.png真机上跑也大概率没问题。但苹果后台在解析你的 App 包时文件系统是大小写敏感的一旦它校验资源引用与真实文件名不匹配就可能把整个包判定为无效。我遇到过一个第三方库它的字体文件名在 bundle 里是小写代码里引用是大写本地开发一直正常上传后却收到 Invalid Binary。排查了将近半天最后是解压 ipa逐个列出资源文件再用脚本比对代码中的引用才定位到。这里建议在工程里搜索所有图片、字体、配置文件名的引用同时去解压后的.app目录里核对真实文件名确保完全一致。3.3 隐性原因二Archive 产物不是你以为的最新代码这一类问题最气人因为你的代码确实没改错问题出在打包流程本身。我见过一个很典型的场景工程师修好了 bug更新了构建号觉得万事俱备打开 Xcode 直接 Archive上传后被判定无效。一看邮件错误码还是之前那个。于是他怀疑是不是苹果后台抽风又传了一次依然无效。最后发现他的 Archive 虽然构建号是新的但产物里的可执行文件对应的是旧代码因为 Xcode 的增量编译没有正确处理某几个 source 文件的变更。处理这类问题别急着重传同一个包。先做一次彻底清理菜单栏 Product - Clean Build Folder按住 Option 键让 Clean 变成深色把 DerivedData 里的缓存一并清掉然后重新 Archive。这里有个很实际的小技巧归档完成后在 Organizer 里右键刚刚产出的 Archive选 Show in Finder进入.xcarchive里的 Products/Applications 目录把.app文件复制出来拖到模拟器或真机上跑一下核心流程确认产物里的内容真的是最新代码再考虑上传。3.4 隐性原因三把自研检查脚本前置别等苹果来打脸既然后台用的是静态检查同样的检查完全可以放到本地 CI 里提前做。我在团队里维护了一个脚本Archive 完成后自动执行三件事检查架构、检查图标 alpha、检查 Info.plist 关键键值。任何一项不过CI 直接标红连上传的机会都不给。这套做法的价值不只是省去来回上传的等待更重要的是把“经验”沉淀成了团队流程。新人加入后不需要把每个坑都踩一遍跑一次 CI 就知道问题出在哪。脚本核心很简单大概长这样APP_PATHpath/to/YourApp.app EXECUTABLEYourApp # 1. 架构检查确认只有 arm64 / armv7 lipo -info $APP_PATH/$EXECUTABLE # 2. 图标透明通道检查路径按实际 Assets 导出位置调整 sips -g hasAlpha $APP_PATH/AppIcon60x602x.png # 3. Info.plist 关键字段检查 plutil -p $APP_PATH/Info.plist | grep -E \ CFBundleVersion|CFBundleShortVersionString|NSCameraUsageDescription|NSPhotoLibraryUsageDescription脚本只需要能在 CI 的 macOS 机器上跑起来就行不需要做得多优雅。关键是形成一个习惯每次提审前先让机器把苹果可能做的检查做一半把明显问题拦在发出之前。3.5 不要把时间浪费在证书上这里必须提一个误区。很多人一看到 Invalid Binary第一反应是“会不会是我证书出问题了”。说实话证书或描述文件出问题通常在上传阶段就会被拒提示通常是签名错误、权限不匹配之类而不是等你上传成功后给你一个 Invalid Binary。二者发生的阶段完全不同前者是传输前的验票后者是收票后的验货。所以如果你收到的状态明确写着 Invalid Binary先把证书相关的事务放一边集中精力排查代码、资源和配置。退一万步讲即使你真觉得证书可疑也可以先用 Xcode 的 Validate 功能验证一下而不是盲目重签后反复上传同一个包那样只会让构建号冲突的坑叠加进来。4. 从收到邮件到重新提交可以直接照抄的排障 SOP4.1 记录失败包的关键信息收到 Invalid Binary 通知后不要立刻改代码先花两分钟记录失败包的信息。打开 Organizer选中那个 Archive记下三个东西版本号 CFBundleShortVersionString、构建号 CFBundleVersion、Bundle Identifier。为什么要记录因为下一步你修改后重新上传时构建号必须是全新且高于之前的。如果你不记录旧值随手填了一个与上次相同的构建号等传到一半才被后台拒绝白白浪费一次上传机会。而版本号如果填低了又会撞上 90061。更好的做法是在项目里用一个结构化的版本管理方案。比如构建号用$(date %Y%m%d%H%M)这种可读时间戳保证单调递增版本号走 Release Train 规则主版本和次版本只增不减补丁版本在提交前手动确认。这样至少在版本字段上不太会出低级错误。4.2 本地把苹果的静态检查提前做一遍这一步相当于把上一节的检查脚本手动跑一遍适合没有 CI 的个人开发者。在重新打包之前先拿到上一次的 Archive 产物确认它真的有问题避免改错方向。具体操作是在 Organizer 里右键失败的那个 Archive选择 Show in Finder然后进入.xcarchive/Products/Applications目录对该目录下的.app文件执行架构检查和图标检查。如果你能在这一步复现出问题说明你已经拿到了根因的一半。如果检查结果全部正常那问题可能出在你没看到的配置文件或依赖项上需要走更深一层的排查比如对比 Dashboard 里的报错描述。我不建议跳过这一步直接重新打包因为你可能只是“猜测”问题出在版本号但实际原因是图标结果改完版本号再传一次依然被拒白白等一轮后台处理时间。4.3 修改之后Clean、Build 号加一、重新 Archive确认问题之后进入修复阶段。无论你改了版本号、图标还是 Info.plist都建议按同一套节奏走这几步。第一步Clean Build Folder。用快捷键 Shift Command K 只 Clean 当前工程如果觉得不放心按住 Option 再点 Product 菜单里的 Clean Build Folder彻底清掉中间产物。这一步能避免增量编译把旧的二进制残留带进新包。第二步在 Xcode 的 General 标签页里把 Build 号加一。注意如果你刚才给版本号改了值也要确认短版本号没有被误改小。第三步重新 Archive。归档时目的地选择 Any iOS Device不要选模拟器。归档完成后在 Organizer 里确认新 Archive 的版本号和构建号确实比你记录到的旧值大再进入下一步。4.4 用 Transporter 上传比 Xcode 更直观上传环节我强烈建议优先用 Transporter而不是直接在 Xcode 里点 Distribute App。原因不是 Xcode 不能传而是 Transporter 在状态提示和错误信息上更清晰尤其是在网络不稳、包比较大时它能给你更明确的反馈。而且 Transporter 支持断点续传上传大包时比 Xcode 稳得多。操作流程在 Organizer 里选中新的 Archive点击 Distribute App选择 App Store Connect最后得到导出的 ipa 文件。然后打开 Transporter把 ipa 拖进窗口点验证验证通过后再点交付。如果验证阶段就报了错误说明包在本地就已经不满足基本要求这时候停下来排查比硬传更有价值。有个小细节要提一下交付完成后Transporter 会显示“已成功交付”之类的状态但这只代表文件上传完毕后台检查还没开始。你需要回到 App Store Connect 的“活动”页面盯着状态从 Processing 变成 Available。这个过程可能需要几分钟也可能更久期间不要重复上传同一个 ipa。4.5 上传后的等待与二次失败处理提交完新包之后给自己定一个规则第一优先级不再是改代码而是等状态落定。我会把后台页面开着隔几分钟刷新一次同时留意邮箱新邮件。如果状态最终变成 Invalid Binary先别慌看这次的错误码跟上次是否相同。如果相同说明你的修复没有命中根因需要回头检查是否真的把最新代码打进了包如果不同说明问题不止一个苹果后台的检查是一次性跑完的它会按规则逐项检查你修掉一个另一个才会浮出水面。这也是为什么我建议你在本地先做完静态检查尽可能把多个问题一次解决而不是被后台牵着走一轮又一轮。还有一点经验之谈如果你连续两次因为不同原因被拒大概率不是运气差而是你的工程里积累了一批历史问题。这时候花一个下午把图标、架构、权限、版本号几类规则彻底过一遍比着急提交审核更划算。5. 四个真实翻车案例复盘每次被拒背后的判断逻辑5.1 案例一2.9.1 想降级发版被 90061 直接打回这个案例发生在一次紧急热修复中。线上版本是 2.10.0因为某个功能出问题产品想快速发一个修复包开发同学顺手把版本号写成了 2.9.1理由是“这是基于 2.9 分支修复的不想动大版本”。上传很顺利后台处理结束后直接 Invalid Binary邮件写着 ITMS-90061。当时几个人都没想明白修复包为什么版本号不能比线上低答案很简单苹果不知道你的分支策略它只认数字比较。2.9.1 小于 2.10.0必须拒绝。处理方式把版本号改成 2.10.1Build 号在原有基础上加一重新 Archive 后上传。整个修复只花了几分钟但等待后台处理和邮件往返浪费了大半天。这个案例告诉我们上架版本号没有“逻辑合理性”只有“数字必须递增”这一条铁律。5.2 案例二CI 机器打出来的包架构比预期多了一个另一个项目用的是自建 CI打包脚本在 xcodebuild archive 命令里设置了一些自定义参数。某天 CI 出来后上传收到 ITMS-90087。排查时我先在本地复现用同一个 tag 在本地 Archive检查lipo -info一切正常再用 CI 产物检查发现二进制里多了一个x86_64架构。根因是 CI 机器安装的某个预编译依赖 frameworkRelease 版本是从模拟器环境打的包混入了模拟器架构而我们的打包脚本没有在最终阶段做架构清理。处理分两步先是把那个 framework 替换成真机版本的预编译包然后在 CI 的打包脚本里加了一段防御性代码在生成 ipa 之前用lipo -remove删掉x86_64和i386架构代码如下APP_BINARY${TARGET_BUILD_DIR}/${EXECUTABLE_PATH} for ARCH in $(lipo -archs $APP_BINARY); do if [ $ARCH i386 ] || [ $ARCH x86_64 ]; then lipo -remove $ARCH $APP_BINARY -output $APP_BINARY fi done这段脚本放进 Build Phase 的 Run Script 里只在 Release 配置下执行。从那次之后架构类错误再没有出现过。我的体会是第三方依赖越多的项目越应该在自己的打包流程里加一道架构过滤不要相信所有第三方库都会自觉发布干净的 Release 包。5.3 案例三设计源文件看起来是白底实际上带透明通道这个案例是典型的“眼见不一定为实”。设计同学给了一张 1024x1024 的 App 图标在 Finder 里预览时显示白底我们主观认为没问题放进 Asset Catalog 就直接归档上传。后台在处理结束后标记无效邮件提示 ITMS-90023说图标含 alpha 通道。当时很不理解因为肉眼看到的就是白底。后来用命令查了一下sips -g hasAlpha icon.png输出hasAlpha: yes这才确认问题。设计软件的画布虽然是白色但导出的 PNG 文件把所有不透明度不足 100% 的区域都记录进了 alpha 通道。处理方式是让设计在导出时勾选“移除透明通道”重新导出但为了应急我用 Python 脚本把透明部分铺成了纯白底from PIL import Image img Image.open(icon.png).convert(RGBA) bg Image.new(RGB, img.size, (255, 255, 255)) bg.paste(img, maskimg.split()[3]) bg.save(icon_fixed.png)这个案例给团队的教训是图标是否带 alpha 通道不能靠眼睛判断必须用工具验证。后来我把sips -g hasAlpha加进了提审前的检查清单。5.4 案例四权限描述写成变量上传后被判定缺失这个问题的隐蔽程度相当高。工程里为了多 Target 复用Info.plist 的部分字段用了$(变量名)的方式动态填充。某个权限的用途描述在 xcconfig 文件里配置成了变量但那个变量在某个 Target 下没有被赋值展开后变成了空字符串。上传后后台认为该 Target 访问了隐私接口但缺少用途描述直接标记 Invalid Binary。本地调试时因为用的是另一个 Target变量有值所以完全没有暴露。排查时看错误码指向权限描述但打开 Info.plist 检查键值又确实存在花了一些时间才意识到键的值是空的。处理方式把该权限的用途描述从变量改成硬编码的中英文双语文案不再走 xcconfig。从那以后我要求团队所有 UsageDescription 的值必须是直接写在 Info.plist 里的字面量不允许用变量、占位符或“待补充”这类文本。苹果后台不关心你的变量有没有值它只看最终产物里的键值是否可用。5.5 这些坑为什么总在提审前爆发复盘这四个案例之后你会发现问题有一个共同点它们全部是“Archive 之后才会暴露”的问题日常开发完全碰不到。日常编译运行用的是 Debug 配置模拟器架构、未验证的权限文案、带透明通道的图标都能正常工作因为系统根本不会给你做上架级检查。这也解释了为什么这些坑总是集中在提审前爆发——因为那是你唯一一次执行完整 Product - Archive - Distribute 流程的时候。所以我现在的建议是把提审动作拆成两条线一条是业务功能验证一条是“上架健康检查”。后者在 CI 里维护一套脚本专门在合并到主干时跑一遍架构、图标、权限、版本号检查。虽然不能完全模拟苹果后台但可以拦截掉 80% 的无效二进制问题剩下的 20% 靠收到邮件后按错误码快速定位基本够用了。我在维护上架流程这几年最大的体会是Invalid Binary 不是玄学它有固定的触发面。你只要做到三件事——Archive 之后先自检、收到错误码先查表再改代码、每次上传前记录好版本号和构建号——这个错误大概率不会再深夜问候你。最后分享一个我自己的习惯每次提审前我都会把上次成功上传的包的 Info.plist 和这次的做一次 diff只改必要字段不顺手升级依赖、不变更工程配置。这能避免大量“改着改着不知道哪个改动导致包无效”的闹鬼问题也算是我用无数次翻车换回来的血泪经验。
返回列表