
1. 为什么需要一套截图尺寸规范生成器做 iOS 开发的人都绕不开上架这一步而真正到了 App Store 提交阶段最容易被忽略又最容易被打回的往往不是功能缺陷而是截图尺寸不匹配。我第一次提交 App Store 时把功能、隐私、权限都检查完结果在提交页面收到一条提示说缺少 6.7 英寸的某种语言截图当时我以为随便截一张“大屏图”就行结果连续被拒了三次整个人都懵了。后来我干脆自己写了一个“iOS 市场截图尺寸规范生成器”把 6.7、6.5、5.5、12.9 这些常见设备尺寸全部整理成配置项配合一个可视化页面和批处理脚本一次性导出所有需要的截图。从那以后我再也没因为截图尺寸的问题被打回过。这篇文章会把生成器的设计思路、技术选型、核心实现和真实踩坑经验完整讲一遍适合独立开发者、出海团队以及第一次准备提交 App Store 的 iOS 开发同学。不管你最后是打算直接复制我的思路自建还是基于这套逻辑去做一个展示工具都希望你能少走一点弯路。1.1 App Store 截图尺寸的坑点复盘很多人会觉得截图不就是在模拟器里按个快捷键吗怎么会出问题。实际上 App Store Connect 对截图的要求比想象中严格很多它不只是验收个大概比例而是直接按像素尺寸判断。比如 iPhone 6.7 英寸和 6.5 英寸一个是 1290x2796一个是 1284x2778两套尺寸差得并不大但你不能用同一张图同时应付两个位置。如果你在后台选择支持所有 iPhone 尺寸就必须逐套准备对应分辨率的截图少一张、错一张上传校验那一步就会直接报错。另一个容易踩的坑是格式问题。App Store 截图要求是 JPG 或 PNG不能带透明通道色彩空间必须是 RGB 或 P3分辨率建议在 72 DPI 左右。虽然我们用 Xcode 模拟器直接截出的图基本符合要求但一旦截图经过某些修图软件、压缩工具或在线转换器处理很容易多出 alpha 通道或者变成灰度色彩空间传到 App Store Connect 就会提示文件无效。这个坑非常隐蔽因为图片在本地打开看着完全正常你能看到的只有 Upload 时的错误信息。除了单张截图还有一个很折腾人的点是数量。App Store 对同一尺寸的截图数量有限制通常是每个尺寸最多十张但如果你在不同语言环境下都有定制截图这个数量会被语言数放大。比如你有中英两种语言每种语言要 6.7、6.5、5.5 三套尺寸每套 3 张那就是 18 张图这还没算 iPad 的尺寸。如果靠手动去改图、重命名、拖进后台不仅耗时而且极其容易漏传。还有一点容易被忽略就是 App Store 截图会自动带有状态栏信息。很多开发者喜欢用设计稿直接导图但设计稿里的状态栏如果不完整或者时间、信号、电池图标跟真实设备不一致会直接影响审核体验。虽然这不是硬性拒绝理由但审核人员一眼就能看出截图是渲染图还是真机图如果大量截图都不带真实状态栏整体可信度会打折扣。所以我在生成器里专门加了状态栏安全区的处理提示目标不是让你伪造截图而是提醒你在出图时保留正确的顶部区域。1.2 自研生成器要解决的核心需求在动手写生成器之前我先把自己遇到的所有痛点列了一份需求清单。首先工具必须内置一套常用的 iOS 截图尺寸预设包括 iPhone 6.7、6.5、6.1、5.5以及 iPad Pro 12.9 和 11 英寸这样我不用每次上 App Store 后台查尺寸表。其次要支持自定义分辨率因为 App Store 的尺寸列表偶尔会更新苹果也会在新的系统版本后增加新机型对应尺寸预留一个手动输入入口能避免工具很快过期。第三也是最关键的一点工具要能处理图片内容本身。我手里的截图素材常常来自不同渠道有的是模拟器直接截的有的是安卓版同事发的参考图还有一些是老版本 App 的截图。它们的分辨率五花八门有些比例接近但差一点有些长宽比完全不同。生成器要能把输入的图片规整到目标尺寸并且尽量不破坏核心画面。这涉及到缩放、裁剪和填充三种逻辑不能只是简单拉伸否则画面会变形审核人员一眼就能看出来。第四导出功能要够稳。我需要一次性生成多张图片并且命名规则要清晰最好直接带上尺寸标识比如 6.7_01.png、6.5_02.png这样传到 App Store Connect 时不会混乱。最后工具最好不用联网所有处理都在本地完成。因为 App 截图涉及产品未发布内容上传到外网工具有泄露风险本地工具最让人放心。这些需求合在一起最后催生了一个非常朴素但足够实用的方案一个纯前端的小网页配合一个可选用的 Python 批处理脚本。网页用来预览和单张处理脚本用来在需要一次性跑几十张图的时候自动完成任务。下面我会把这些实现细节逐步拆解。2. 工具设计与技术栈选择确定需求之后技术栈的选择反而是最简单的事。我没有用 App、没有用复杂框架也没有买服务器而是直接用一个 HTML 文件加少量 JavaScript再加上一个几十行的 Python 脚本把整个流程跑通。这么做的好处是第一没有依赖环境随便一台电脑打开浏览器就能用第二不产生网络请求截图不会离开本机第三后续想扩展功能只需要在本地改代码不需要重新走一遍开发、测试、发布流程。2.1 功能范围与交互流程设计生成器的用户行为被我设计得非常简单一共就三步。第一步用户选择一张或多张原始图片图片会显示在预览区同时工具自动读取图片的原始像素尺寸。第二步用户从尺寸预设列表里选择要输出的目标规格比如选择“iPhone 6.7 英寸”工具会立刻把图片按目标比例处理并生成预览。第三步用户点击导出工具把处理后的图片下载到本地。但这里有一层额外的判断逻辑很重要的一个环节是“比例适配”。原始图的比例和目标图的比例往往不一样常见的处理方式有三种缩放后裁剪缩放后留白边直接拉伸填满。我默认选择的是“等比缩放后居中裁剪”因为 App Store 截图最重要的信息内容通常集中在中间区域边缘稍微裁掉一点影响不大反而比留黑边更自然。同时我留了一个复选框让用户可以在“居中裁剪”和“留白边”两种模式之间切换照顾极端场景比如横版图要转成竖版截图。另一个交互细节是“安全区参考线”。App Store 截图顶部有状态栏区域底部有 Home Indicator 区域如果你把重要的操作按钮放在这些区域后续可能有被系统 UI 遮挡的风险。我在预览画布上画了两条半透明参考线提示用户核心内容不要越过这块区域。这张参考线只存在于预览层级不会画到导出图片里当然如果你想让它一起导出也可以加一个开关来控制。预览和导出的逻辑我尽量做得所见即所得画布上显示什么导出图片就是什么。这里有一个容易被新手忽略的问题就是浏览器的 Canvas 在处理高清图时会有性能上限。1290x2796 这样的分辨率已经接近 360 万像素如果同时加载五六张大图内存占用会瞬间飙升。所以我在实现时做了限制预览阶段用缩小后的图片显示导出阶段才加载原始大图。这样做既保证了界面流畅又保证了导出图清晰度。2.2 用纯前端还是脚本工具纯前端方案最大的优势是即时反馈。你把文件往浏览器里一拖马上就能看到适配效果不需要安装任何软件也不需要记命令行。如果你的场景只是每周做一两次更新或者你需要根据设计反馈随手调整构图网页工具的效率非常高。而且现代浏览器对 Canvas 的支持已经很成熟导出 PNG、JPEG 都支持我甚至不需要引入任何第三方库。但纯前端也有短板比如当你要处理几十张截图、做多语言多尺寸组合时在网页里一张一张导还是很费事。这种批量场景更适合用脚本。我用 Node.js 也可以但考虑到 App 截图大多是团队成员直接提供最好少让同事折腾环境所以我选择用 Python 写一个命令行工具因为大多数后端或自动化同学电脑里都有 Python 环境而且 Python 处理图片生态非常成熟Pillow 库一个依赖就搞定。我把两种能力做成了同一个工具的两种使用形态网页负责单张精细处理脚本负责批量自动化。中间的数据模型是通用的尺寸预设表两边共用同一份 JSON这样以后苹果更新尺寸规范我只需要改一次配置网页和脚本都会同步。考虑到团队协作场景我还允许通过命令行传入一个 CSV 文件里面写好“图片路径、目标尺寸、输出文件名”脚本按表跑批能省下大量手工传参的时间。有人可能会问为什么不直接用 Sketch、Figma 或者在线网站现成功能非要从头写一个生成器。答案其实很简单外部工具要么收费要么需要开通账号更关键的是尺寸模板大多更新不及时。自己做最大的价值不是说工具做得比商业软件好而是它完全贴合自己的流程比如可以把 App 名称、副标题的文字排版直接写进生成逻辑导出后就接近成稿效果省掉一轮去设计软件里排版的时间。3. 核心实现细节与实操要点这一部分是整篇文章的重点我会把生成器的代码结构、尺寸参数、图片处理逻辑完整讲清楚。即使你不想照抄我的方案里面的很多细节也值得你在处理 App Store 截图时参考。3.1 尺寸预设库的搭建所有截图处理的起点都是一个可靠的尺寸配置表。我根据自己整理资料和实际提交经验把常用规格做成了如下预设预设名称适用机型像素尺寸宽 x 高iPhone 6.7 英寸iPhone 14 Pro Max / 15 Pro Max / 16 Pro Max 系列1290 x 2796iPhone 6.5 英寸iPhone 11 Pro Max / XS Max 等1284 x 2778iPhone 6.1 英寸iPhone 14 / 15 / 16 系列1179 x 2556iPhone 5.5 英寸iPhone 8 Plus / 7 Plus 等1242 x 2208iPad Pro 12.9 英寸iPad Pro 12.9 第三代及后续2048 x 2732 竖屏 / 2732 x 2048 横屏iPad Pro 11 英寸iPad Pro 11 第一代及后续1668 x 2388 竖屏 / 2388 x 1668 横屏需要说明的是App Store Connect 在不同时期展示的尺寸入口会有微调同一机型在不同 iOS 版本里的截图规格也可能存在差异。因此我把这套表做成了“可覆盖配置”在代码里以一个对象存储方便随时修改。下面是我在 JavaScript 里的写法const SIZE_PRESETS { iphone-67: { label: iPhone 6.7 英寸, device: iphone, width: 1290, height: 2796, advice: 适用于 iPhone 14 Pro Max 之后的 6.7 英寸机型 }, iphone-65: { label: iPhone 6.5 英寸, device: iphone, width: 1284, height: 2778, advice: 适用于 iPhone 11 Pro Max / XS Max }, iphone-61: { label: iPhone 6.1 英寸, device: iphone, width: 1179, height: 2556, advice: 适用于近几代 6.1 英寸标准版机型 }, iphone-55: { label: iPhone 5.5 英寸, device: iphone, width: 1242, height: 2208, advice: 适用于 iPhone 8 Plus 等小屏机型 }, ipad-pro-129: { label: iPad Pro 12.9 英寸, device: ipad, width: 2048, height: 2732, orientation: portrait, advice: 同时支持 2732 x 2048 横屏方向 }, ipad-pro-11: { label: iPad Pro 11 英寸, device: ipad, width: 1668, height: 2388, orientation: portrait, advice: 同时支持 2388 x 1668 横屏方向 } };这段代码的核心作用是维护一份“单一事实来源”所有地方引用尺寸时都从这份表里读不会出现网页里写一套、脚本里又写另一套的问题。如果你想把横向截图也纳入流程只需要增加一条新预设把宽高对调即可。Python 脚本里的配置可以完全复用同一个概念。因为我不想维护两处配置所以直接让 Python 脚本读取同一份 JSON 文件。这里有一个小建议如果你做的是团队工具配置文件最好和代码分离不要硬编码在脚本里这样产品和设计同学也能在不碰代码的情况下自己加一个尺寸模板。3.2 图片缩放、裁剪与安全区处理拿到原始图片后下一步就是把它处理成目标尺寸。核心逻辑可以拆成四步计算缩放比例、居中裁剪、绘制到画布、输出图像。我以 JavaScript 的 Canvas 实现为例这段代码是生成器最核心的部分。function processImage(sourceImage, targetWidth, targetHeight, mode cover) { const canvas document.createElement(canvas); canvas.width targetWidth; canvas.height targetHeight; const ctx canvas.getContext(2d); // 计算等比缩放到目标尺寸的临时大小 const srcWidth sourceImage.naturalWidth; const srcHeight sourceImage.naturalHeight; const scale Math.max(targetWidth / srcWidth, targetHeight / srcHeight); const scaledWidth Math.round(srcWidth * scale); const scaledHeight Math.round(srcHeight * scale); // 居中裁切区域 const offsetX Math.round((scaledWidth - targetWidth) / 2); const offsetY Math.round((scaledHeight - targetHeight) / 2); ctx.fillStyle #ffffff; ctx.fillRect(0, 0, targetWidth, targetHeight); ctx.drawImage( sourceImage, offsetX, offsetY, scaledWidth, scaledHeight ); return canvas; }这段代码的关键是计算缩放比例时用了Math.max而不是Math.min。区别在于使用Math.max会先把图片放大到“宽和高都超过目标尺寸”然后再居中裁剪最终填满整张图不会留下白边。这就是 CSS 里object-fit: cover的效果。如果改用Math.min图会完整显示但四周会有空白相当于object-fit: contain适合不想丢内容的场景。实际使用中还要考虑一个隐藏问题就是图片的 DPI。JPG 文件内部带有 DPI 元数据浏览器在处理时通常会忽略它但如果你把处理后的图再交给某些严格校验工具可能因为 DPI 数值异常而提示文件不合格。为了保证万无一失我在导出时会显式写入 72 DPI 这类基础属性。在浏览器 Canvas 中这一步需要用toBlob或toDataURL导出PNG 格式本身就能保留必要的元信息一般不会出问题。安全区的处理不像很多人想的那样需要检测图像内容而是基于设计规范做一层参考线提示。状态栏高度在不同机型上不一致比如刘海屏和有 Home 键的机型状态栏高度差距很大。我在配置表中额外维护了一个safeAreaTopRatio参数它表示安全区顶部占整图高度的比例默认大约是 0.07。绘制参考线时我按这个比例创建一个半透明矩形用户预览时就能看出来哪些区域可能被系统 UI 遮挡。真实的 App Store 审核不会因为你把按钮放在状态栏区域就拒绝但会给人一种不专业的感觉所以我坚持在生成器里保留这条提示线。3.3 导出与批处理逻辑导出图片的格式我默认设置成 PNG因为截图里通常包含大量文字如果转成 JPG边缘会有压缩痕迹尤其是在按钮描边或深色背景的文字处画质下降非常明显。PNG 文件体积大一些但 App Store 上传并没有严格的截图体积限制完全没必要为省几 MB 去牺牲清晰度。如果你坚持要 JPG 格式也可以在导出时设置质量参数。我在代码里预留了quality选项默认是 0.95属于视觉无损级别。还有一点要注意Canvas 导出 JPG 时背景默认是黑色透明如果你没有先绘制白色背景导出的图会黑乎乎一片。这是一个特别容易踩的坑我第一次写的时候就是漏了背景填充导出了几张黑色底图在后台预览才发现。批量处理脚本我放在了本机的 Terminal 里跑Python 版本专门用于处理大量截图。核心思路是循环读取一个 CSV 清单每行指定源文件路径、目标预设、输出路径然后调用 Pillow 库执行类似 Canvas 的操作。Pillow 的Image.resize方法默认用最近邻插值画质比较差我一般显式指定Image.LANCZOS它能在缩放时保留更多细节在缩小高清截图时效果尤其明显。完整代码如下from PIL import Image import csv, os def crop_to_cover(img, target_w, target_h): src_w, src_h img.size scale max(target_w / src_w, target_h / src_h) new_w int(src_w * scale 0.5) new_h int(src_h * scale 0.5) img img.resize((new_w, new_h), Image.LANCZOS) left (new_w - target_w) // 2 top (new_h - target_h) // 2 return img.crop((left, top, left target_w, top target_h)) def export_preset(source_path, out_path, width, height): img Image.open(source_path).convert(RGB) img crop_to_cover(img, width, height) img.save(out_path, PNG, dpi(72, 72)) with open(tasks.csv, r, encodingutf-8) as f: for row in csv.DictReader(f): export_preset( row[source], row[output], int(row[width]), int(row[height]) ) print(fdone: {row[output]})这段脚本最简单的用法是把需要处理的截图和尺寸要求写进tasks.csv保存文件后执行python batch_screenshot.py脚本会遍历所有任务并输出图片。这里有个经验如果是在 Mac 上跑建议用python3而不是python因为新版 macOS 自带的 Python 版本比较旧Pillow 安装后也可能因为环境变量找不到。我遇到过好几次明明装了 Pillow一执行却报ModuleNotFoundError查到最后都是 PATH 指向了系统自带的 Python 2 环境。4. 常见问题排查与上架实战工具写出来只是第一步真正把它用到上架流程中会遇到不少奇奇怪怪的问题。这一节我会把高频问题整理成速查表再讲一下从生成器导出截图到 App Store Connect 后台提交的完整流程。4.1 高频问题速查表以下表格基于我实际使用中踩过的坑以及身边同事反馈过的典型案例整理而成现象可能原因处理办法上传截图提示“缺少尺寸”所选设备尺寸与截图实际像素不匹配回到生成器重新选择目标尺寸并导出原分辨率图片提示“必需的语言缺失”某个语言版本没有传齐全套尺寸对每个语言补全所有尺寸生成器导出的文件名要规范截图被提示“包含透明通道”原图是带 alpha 通道的 PNG未经扁平化在导出时强制合成到白色背景或先转成 JPG 再上传预览时图片变形处理逻辑里使用了拉伸填充改用代码里的居中缩放裁剪逻辑不要直接改宽高导出 JPG 后变成黑底没有先填充背景色绘制前先填充#ffffff背景图片看起来模糊缩放时插值算法选错或放大了小图使用 LANCZOS 插值尽量提供分辨率不低于目标尺寸的原图模拟器截图传到后台尺寸对不上模拟器窗口比例和设备真实分辨率不一致使用模拟器的“物理尺寸”输出或在生成器里用目标预设强制转换多张截图顺序乱了文件名没按规范排序统一命名为6.7_01.png、6.7_02.png上传时按名称排序这里面最值得多说两句的是最后一条截图顺序的问题。App Store 后台允许你拖拽调整截图的展示顺序但如果你一次传了几十张图手动排序会让人崩溃。我的做法是在生成器导出时文件名一定带上尺寸和序号比如1290x2796_1.png、1290x2796_2.png这样在后台默认按文件名排序后顺序基本就是对的只需要微调少量截图。还有一个问题经常发生在“模拟器截图”场景。模拟器里看到的画面尺寸不一定是最终导出的像素尺寸尤其当你把模拟器窗口缩放显示时截图里实际记录的分辨率可能跟最终设备分辨率有偏差。解决方式有两种一种是在模拟器里用File Save Screen菜单保存这会输出模拟器当前窗口的真实分辨率更好的做法是直接让生成器做一步标准化处理不管原图是什么尺寸最终统一输出为目标预设。4.2 从生成器到 App Store Connect 的完整衔接工具做完之后我的照片处理流程变成了一条非常机械化的流水线。第一步从设计稿或模拟器中拿到原始截图第二步把原始截图放进生成器选择目标尺寸第三步在预览界面检查安全区参考线范围内是否有重要元素如果有就回到设计稿里调整布局再重新导出第四步批量命名并保存到指定文件夹第五步打开 App Store Connect上传并在后台做最终预览。这里我想特别强调第五步里的“后台预览”环节。很多人上传成功后就不管了直接点提交审核但在 App Store Connect 的后台预览里Apple 会展示截图的完整效果包括在系统 UI 加持下的样子。你最好逐张点开检查特别是状态栏区域如果时间、信号图标被裁掉或者被大标题遮挡观感会很差。还有一点是文案检查多语言环境下截图里的文字可能因为宽度变化而折行你在生成器预览时看到的英文效果和最终后台渲染效果通常一致所以一定要提前确认。另外关于 iPad 横屏截图的问题。更新之后 App Store 对横屏截图的支持越来越细如果你的 App 支持 iPad 横屏那截图最好同时准备横屏和竖屏两套否则在审核时可能被判定为“未完整适配 iPad”。我的生成器里专门为 iPad 预设增加了横屏选项处理逻辑很简单就是把目标宽高对调其余裁剪逻辑完全一样。不要觉得多准备一套图很浪费审核体验影响排名值得投入这一步。5. 个人实操体会工具本身并不复杂但它在整个上架流程里帮了我大忙。最直接的变化是我不用再为一张图片反复打开设计软件也不用临时去查某个机型的具体分辨率。所有尺寸规则都沉淀在生成器配置里团队里其他人拿到这份工具几分钟就能上手效率提升非常明显。最后再分享一个小技巧生成器的尺寸配置表不要只放当前 App Store 需要的规格我建议把历史上出现过、以后可能还会用到的尺寸都留下来比如更早的 iPad 或 iPhone 机型。因为 App Store 后台偶尔会调整可选尺寸尤其是新机型发布后很多旧尺寸可能会被合并或替换。你手上有完整的历史尺寸库遇到需要补老机型截图的时候就能直接出图不用临时翻资料。如果你准备做一个类似的工具我会建议先把配置表和图片处理核心逻辑写好界面上只要做到能用就好不必追求完美。因为你自己用起来的痛点会告诉你下一步该加什么功能可能是多语言批量处理也可能是自动添加水印这些都可以后续迭代。工具永远是越用越顺手而不是越设计越完美。