
做iOS开发这几年我最不想碰的活儿就是“切图标”。一张设计稿按苹果的规格表手动导出十几个尺寸从20像素的通知栏小图到1024像素的商店大图中间还分iPhone和iPad两套命名不能乱、透明通道不能有、圆角不能自己加稍不留神就被审核打回来。后来我换了个思路只维护一张1024像素的正方形主图剩下所有尺寸全部交给自动化工具体系批量生成顺便把Xcode资产目录需要的配置文件也写好整个过程几分钟就完事。今天这篇就围绕“一张图生成iOS应用Icon各种尺寸”这个主题把工具选型、实操流程和那些文档里不会写的坑一次讲清楚。这篇文章适合独立开发者也适合团队里负责打包的同事直接拿去套用。1. 先把iOS图标规格表吃透才知道工具该生成哪些尺寸很多教程上来就让你“找个工具生成”但如果你自己都不知道要生成哪些尺寸拿到工具一样会出问题。我建议先花两分钟把规格表过一遍这样后面玩任何工具心里都有底。1.1 iPhone、iPad全量尺寸清单iOS图标的规格体系可以拆成三块iPhone、iPad、App Store商店展示。每一块里又按“逻辑尺寸 × 倍率”得到实际像素。逻辑尺寸的单位是pt倍率是1x/2x/3x两者相乘才是最终图片的像素尺寸。很多新手直接把逻辑尺寸当像素去切图这里必须先纠正。平台逻辑尺寸倍率实际像素用途iPhone20x202x / 3x40 / 60通知栏、设置列表iPhone29x292x / 3x58 / 87设置、搜索iPhone40x402x / 3x80 / 120主屏幕、搜索iPhone60x602x / 3x120 / 180主屏幕iPad20x201x / 2x20 / 40通知栏iPad29x291x / 2x29 / 58设置iPad40x401x / 2x40 / 80主屏幕iPad76x761x / 2x76 / 152主屏幕iPad Pro83.5x83.52x167主屏幕App Store1024x10241x1024商店展示合计下来一套UniversaliPhone iPad App Store图标通常需要18个PNG文件。注意83.5x83.5这个逻辑尺寸是带小数点的实际像素是167而不是168很多工具在这个数字上做过翻转如果你手工切图这里特别容易写错文件名或算错像素。1.2 为什么“一张大图”不能直接传可能有人会问系统不会自己缩放吗为什么非要我交这么多尺寸原因是iOS在渲染图标时是按固定像素读取对应文件的通知栏读的是20pt那一档主屏幕读的是60pt或76pt那一档资产目录里没有对应文件系统就会给你渲染出一个默认占位图丑且不可控。Xcode提供了“Single Size”选项可以只放一张1024大图让Xcode在构建时自动生成其余尺寸。这个功能对快速验证很友好但有两个问题一是App Store上传时仍然需要单独提供1024图标二是构建阶段的自动缩放你没机会手动干预万一某档尺寸效果不理想也没法单独替换。所以现在的正式项目里大多数人还是选择一次性生成全套PNG明确可控也和团队里的设计流程更好配合。我自己走“一张主图 批处理工具”的路线本质上把“维护”这件事收敛到一张源图上改设计只改这一张重跑一遍脚本所有尺寸同步更新不会出现“改了主图忘记重新导出小图”这种事故。2. 生成工具的三种思路按场景选2.1 在线生成器胜在快但别随便传图现在很多在线工具站都支持“上传一张图自动生成全套Icon”对个人项目或者Demo来说非常方便打开网页、拖图进去、下载zip几秒钟搞定。我最早也是这么干过来的省事是真省事。但用这类工具要谨慎几点。第一是隐私正式项目的设计稿在没发布之前属于内部资产传到第三方服务器有一定风险公司项目或者有保密协议的项目我不建议用。第二是质量我实测过多个在线生成器有的输出1024图带透明通道有的文件名和标准不一致还有的在小尺寸上处理得特别糊你下载完必须逐个检查。第三是可用性一旦在离线环境或者内网开发这类工具直接废掉。2.2 设计软件插件的导出预设如果你平时就是用设计软件画图标更好的思路是在里面建立导出预设需要切图时一键导出全部尺寸。好处是源图是矢量的导出清晰度有保障而且和设计流程无缝衔接设计师自己就能搞定不用每次找开发。缺点是依赖设计工具环境团队里不是每个人都有这个软件另外每次都要人工触发导出自动化程度还是差一口气。如果你是一个人在维护全流程脚本方案会更省心。2.3 脚本批处理我最推荐的长期方案我最推荐的是脚本方式Python 图像处理库Pillow写一个独立脚本放在项目仓库里。跑一次就生成全部尺寸自动写Contents.json顺便检查每张图的尺寸和透明通道全程不需要打开任何图形界面。为什么脚本方案长期用下来最舒服因为它是可复现、可验证、可继承的。新建项目时把脚本复制过去改一下源图路径就能用CI里也能挂一道校验谁改了图标尺寸不对直接报错。在线工具做不到这些设计插件也做不到全自动。下面我就把完整脚本和用法展开讲。3. 一张1024主图生成全套Icon的完整实操3.1 源图准备的三个硬性要求源图质量决定了全套成品的质量这一步千万别省。我的要求就三条第一必须是无透明通道的1024x1024正方形PNG或JPEG。如果你是从设计软件导出源文件务必确认最终导出的图不带alpha通道原因后面会专门说。第二不要预先加圆角。iOS系统会自动给图标套一层圆角遮罩如果你自己把角切圆了最终显示会是“圆角里套圆角”四角还会露出背景色非常难看。老老实实给满幅正方形即可。第三核心内容要居中并留出安全边距。苹果官方的建议是图标四周大约有10%的区域会在裁切和圆角遮罩中损失掉所以重要内容最好控制在中央约80%的区域内。很多新人把图形画满全幅结果小尺寸下边缘被切得七零八落。文件名也顺手规范一下不要用中文、不要带空格全小写加连字符最稳。3.2 批处理脚本的完整实现脚本逻辑并不复杂读入主图按规格表逐项缩放保存PNG最后生成一份Contents.json。下面是我在项目里实际用的版本你复制到本地、装好Pillow就能跑。pip install pillow#!/usr/bin/env python3 import os import json from PIL import Image SRC master_1024.png OUT AppIcon.appiconset # (逻辑尺寸, 倍率, 设备平台, 输出文件名) SPECS [ # iPhone (20x20, 2x, iphone, Icon-iphone-202x.png), (20x20, 3x, iphone, Icon-iphone-203x.png), (29x29, 2x, iphone, Icon-iphone-292x.png), (29x29, 3x, iphone, Icon-iphone-293x.png), (40x40, 2x, iphone, Icon-iphone-402x.png), (40x40, 3x, iphone, Icon-iphone-403x.png), (60x60, 2x, iphone, Icon-iphone-602x.png), (60x60, 3x, iphone, Icon-iphone-603x.png), # iPad (20x20, 1x, ipad, Icon-ipad-201x.png), (20x20, 2x, ipad, Icon-ipad-202x.png), (29x29, 1x, ipad, Icon-ipad-291x.png), (29x29, 2x, ipad, Icon-ipad-292x.png), (40x40, 1x, ipad, Icon-ipad-401x.png), (40x40, 2x, ipad, Icon-ipad-402x.png), (76x76, 1x, ipad, Icon-ipad-761x.png), (76x76, 2x, ipad, Icon-ipad-762x.png), (83.5x83.5, 2x, ipad, Icon-ipad-83.52x.png), # App Store (1024x1024, 1x, ios-marketing, Icon-1024.png), ] PIXELS { 20x20: 20, 29x29: 29, 40x40: 40, 60x60: 60, 76x76: 76, 83.5x83.5: 83.5, 1024x1024: 1024, } SCALES {1x: 1, 2x: 2, 3x: 3} os.makedirs(OUT, exist_okTrue) img Image.open(SRC) # 关键压平透明通道避免生成带alpha的PNG if img.mode RGBA: background Image.new(RGB, img.size, (255, 255, 255)) background.paste(img, maskimg.split()[3]) img background.convert(RGB) for size, scale, idiom, filename in SPECS: px int(round(PIXELS[size] * SCALES[scale])) resized img.resize((px, px), Image.LANCZOS) resized.save(os.path.join(OUT, filename)) # 生成 Contents.json images [] for size, scale, idiom, filename in SPECS: images.append({ filename: filename, idiom: idiom, scale: scale, size: size, }) contents {images: images, info: {author: xcode, version: 1}} with open(os.path.join(OUT, Contents.json), w, encodingutf-8) as f: json.dump(contents, f, indent2, ensure_asciiFalse) print(f已生成 {len(images)} 张图标到 {OUT}/)代码里有两个细节值得说明。一是用了Image.LANCZOS作为缩放算法这是图像处理库中质量较高的下采样算法从1024缩到20像素这种大倍率缩放它能最大程度保留边缘细节如果用默认的最近邻算法小尺寸会出现明显锯齿。二是做了RGBA到RGB的铺底处理把透明区域用白色背景压平再缩放防止生成的PNG残留alpha通道这一步对审核非常重要。3.3 生成Contents.json并接入XcodeContents.json是Xcode资产目录的“说明书”每条记录把文件名与设备类型、逻辑尺寸、倍率对应起来。Xcode读到这份文件后就知道该往哪个设备放哪个图标。脚本已经把它一并生成好了使用方式如下在Xcode中打开Assets.xcassets找到AppIcon如果工程模板里没有就新建一个AppIcon。选中AppIcon后把脚本生成的AppIcon.appiconset文件夹里的全部文件包括Contents.json拖进去覆盖。在TARGETS的General页签下确认App Icon Source指向当前这个AppIcon即可。如果你不想用脚本也可以直接在Xcode里把资产目录的图标位一张张拖图填充但那个操作极其繁琐我手动拖过一次之后就没再尝试第二次了。脚本一步到位而且是确定性输出同一个源图每次生成结果完全一致这在工作交接时特别有价值。4. 生成之后最容易踩的五个坑4.1 alpha通道App Store审核的高频拒因我真实遇过图标一切正常提交App Store后收到反馈说“图标不能包含透明通道”。排查半天根源是一张带alpha通道的源图被在线工具改成了PNG输出缩小时的透明边缘也一起留了下来。解决方案就是脚本里那段RGBA转RGB逻辑把透明区域用白色背景铺底。你可以用macOS自带命令检查一张PNG是否残留透明通道sips -g hasAlpha Icon-1024.png输出yes就说明还有透明通道必须重新铺底处理。我建议把这步做成强制校验输出后全部为no再往上传。4.2 圆角千万别自己加这个和源图准备里说的一样我再强调一次。很多设计同学习惯在导出时顺手加个圆角觉得“图标本来就是圆的嘛”。但iOS是通过系统级遮罩统一处理圆角的你提前加了圆角真机上就是双重圆角而且圆角外区域会露出你填的背景色或透明观感很差。源图永远是满幅正方形剩下的交给系统。4.3 83.5这个奇葩尺寸83.5x83.5是iPad Pro主屏幕图标专属逻辑尺寸2x后是167像素。它是半整数手工计算时极容易出错常见错误是算成168或者干脆漏掉这个尺寸。脚本里用round()处理像素整数化既不会出现浮点尺寸也不会四舍五入错位这就是我坚持用脚本的重要原因之一。4.4 小尺寸图标模糊1024缩到20像素信息量损失巨大。如果你的原图细节过多20像素下会糊成一团。经验做法是为主图准备两个层级大尺寸用复杂原图小尺寸尽量用粗线条、大色块、高对比的图形。做不到的话至少确保主图核心图形在缩小之后仍然可辨认细节别堆太满。我在一个项目里就吃过亏原图是一条很精致的渐变线条龙60像素下还好20像素下完全成了一坨灰最后重新设计了一套简化版才解决问题。4.5 Contents.json写错手写Contents.json最容易错的地方是idiom、size、scale三个字段的对应关系比如把iPhone的尺寸标成ipad或者把scale写反。Xcode加载时会提示“不完整”或警告App Store审核甚至可能匹配错图标。用脚本自动生成能完全规避这类问题因为规格表是程序里固化的不会出现人为笔误。下面对应关系做个速查表方便你排查症状常见原因解决办法审核提示图标带透明通道源图或输出PNG含alpha脚本RGBA转RGB或用sips检查真机图标圆角处露白边源图预加了圆角重新导出满幅正方形iPad Pro图标缺失或错位漏了83.5逻辑尺寸用规格表核对是否生成167像素小尺寸图标成一团糊原图细节太多简化图形或准备两套主图Xcode提示图标不完整Contents.json字段写错改用脚本自动生成JSON5. 一些实战心得与进阶技巧5.1 加一个校验脚本兜底批处理脚本生成完我还会跑一个校验脚本把每个文件的尺寸、透明通道、命名全部检查一遍。简化版如下import os from PIL import Image DIR AppIcon.appiconset EXPECTED { Icon-iphone-202x.png: 40, Icon-iphone-203x.png: 60, # ... 按规格表补全 } for name, px in EXPECTED.items(): path os.path.join(DIR, name) if not os.path.exists(path): print(f缺少文件: {name}) continue im Image.open(path) if im.size ! (px, px): print(f尺寸错误: {name} 应为 {px}x{px}, 实际 {im.size[0]}x{im.size[1]}) if im.mode RGBA: print(f含透明通道: {name})这个校验脚本可以作为CI的一个检查步骤谁改动图标提交代码只要不通过就挡住省心很多。5.2 多项目复用的正确姿势我的做法是把生成脚本放在一个公共工具仓库里用命令行参数指定源图路径和输出目录。新项目要接图标时一行命令就能完成生成和校验。整个流程从“手动切图半小时”缩短到“跑脚本两分钟”而且不再需要对着苹果规格表查来查去。5.3 别忘了真机预览最后提醒一个容易被忽略的步骤生成的图标一定要在真机上跑一遍重点看主屏幕图标和设置页图标。模拟器里有些渲染差异真机上才能看出小尺寸的清晰度和圆角遮罩效果。我通常在开发机上连一台真机装上测试包把主屏幕和设置页都滑一遍没问题再提交。这套流程我现在已经用在了好几个项目上最大的感受就是“心里有底”。以前每次发版都担心图标哪个尺寸漏了现在源图更新一条命令搞定校验脚本再兜底一道审核那边再没因为图标被退回过。如果你还在手动切图强烈建议把这套工具链一次性搭起来省下来的时间足够你多测几个真机页面了。