SF Symbols 内置了 6,000 多个图形,可以像文字一样缩放、调整粗细和颜色。但有时你需要的图形并不在其中——通常是你自己的 logo 或某个特定领域的图标。解决方法是自己制作一个行为完全一致的符号:随 Dynamic Type 缩放,响应 .foregroundColor,随系统字体切换粗细。以下是完整的制作流程。
SF Symbols 的特别之处不在于它们是矢量图——而在于它们与系统字体是关联索引的。当用户选择 XL Dynamic Type 字号时,每个系统符号都会随之缩放。当你切换到粗体字重时,符号的笔画也会相应加粗。你的自定义符号也能做到这些,但前提是你必须以正确的模板格式提供它,并将其作为"Symbol Image"导入资产目录——而不是随意放一个 SVG 文件。
"自定义符号" SVG 是一个包含特定图层 ID、三条水平参考线,以及(通常)九个预绘制变体的 SVG 文件——三种尺寸(Small、Regular、Large)× 三种字重(Ultralight、Regular、Black)。SF Symbols 应用要求文件严格遵循这一结构,Xcode 的"Symbol Image"资产类型也知道如何读取它。
你不需要从头绘制全部九个变体。标准流程如下:
完成后,你的自定义符号就能像系统符号一样使用——在 SwiftUI 中用 Image("custom-name"),用 .font(.title) 缩放,用 .foregroundStyle(.red) 上色。
打开 SF Symbols 应用(Apple 免费提供)。找到一个形状和比例与你想绘制的内容相近的系统符号,右键点击并选择 Export Symbol…——弹出的对话框会询问保存位置以及模板版本(选择你的最低系统版本所支持的最新版本)。
导出的文件可以在任何矢量工具中打开——Figma、Illustrator、Sketch,甚至 Inkscape。你会看到:
这些参考线非常重要。它们决定了你的符号与周围文字并排时的对齐方式。如果字形的垂直范围不符合参考线,符号放在文字旁边时就会显得错位。
generate_image 工具,接入了 Gemini。你可以发出指令:"生成一张 1024×1024 的单色图形:程式化的罗盘玫瑰,黑色背景透明,适合用作图标",助手会把结果保存到 <project>/assets/。输出的图片还不是模板格式,但它能给你一个干净的参考形状,供你在 Figma 中描摹,或直接作为第 4 步的源图导入 AI 的提示词。把它当作草图工具,而非最终资产。
在你的矢量工具中,选中中央的"Regular Regular"字形并替换为你的图形。注意以下限制:
Symbols、Notes、Guides 以及变体格子的名称是 SF Symbols 导入器识别的关键,重命名会导致导入失败。.symbolRenderingMode(.hierarchical) 渲染模式下,路径按图层顺序上色;如果形状不一致,颜色就会落在错误的位置。对于其他变体:将 Regular 格子复制到 Small 和 Large 中(Xcode 本来就会从中央格子缩放,但提供预缩放版本能获得更清晰的效果)。如果时间允许,将 Regular 复制到 Ultralight(更细的笔画)和 Black(更粗的笔画)。如果没时间,留空也没关系,Xcode 会回退到 Regular 字重。
如果你的 logo 已经是干净的 SVG,AI 助手通常可以直接将其包装成合法的符号模板,而不需要你打开 Figma。在项目中开启一个 Claude 聊天,然后提问:
I have a logo at ~/Desktop/brand-mark.svg. Generate a custom SF Symbol
template (Symbol 4.0, 9-variant) that uses this logo as the Regular Regular
cell and scales it for the other 8 cells. Save it as
MyApp/Assets.xcassets/BrandMark.symbolset/BrandMark.svg with the matching
Contents.json.
助手会生成两个文件:模板 SVG(包含全部九个格子、正确的 ID 和参考线)以及一个小型 Contents.json,用于将其注册为 Symbol Image。在 Xcode 中打开资产目录进行验证——新符号应出现在 Symbol Image 分类下,并在每种字重下都有预览。
如果助手的第一次尝试看起来有偏差——通常是因为源 logo 的比例不符合字体字形的比例——把资产目录预览的截图粘贴回去,让它调整缩放比例或垂直位置。
systemName 变为普通名称系统符号使用 systemName,自定义符号不用:
// System symbol
Image(systemName: "star.fill")
.font(.title)
.foregroundStyle(.yellow)
// Custom symbol — same modifiers, different initializer
Image("BrandMark")
.font(.title)
.foregroundStyle(.yellow)
这就是 API 上的全部区别。一旦你的自定义符号进入资产目录,所有 SF Symbols 修饰符——.font()、.foregroundStyle()、.symbolRenderingMode()、.symbolEffect()——都能完全一致地作用于它。你可以把自己的 logo 和 "star.fill" 放在同一个 HStack 里,它们会一起对齐、缩放和着色。
UIKit 中的等价写法是:自定义符号用 UIImage(named: "BrandMark", in: nil, with: nil),系统符号用 UIImage(systemName:)。
.svg 扩展名的 PNG 也算)、模板中缺少图层 ID,或者资产目录条目是普通的 Image Set 而非 Symbol Image Set。删除该条目,重新拖入 SVG——Xcode 的"New Symbol Image Set"会创建正确的条目类型。如果你是通过"New Image Set"添加的,那就进错了地方。
以下情况值得使用自定义符号的开销:
.foregroundStyle,而不是为不同颜色分别维护多个变体。以下情况可以跳过自定义符号流程,直接使用普通矢量图或 PNG: