教程 搜索 / 原生 Mac IDE / 创建自定义 SF Symbol
📝 文字 ● 中级 更新于 2026-05-17

创建自定义 SF Symbol

SF Symbols 内置了 6,000 多个图形,可以像文字一样缩放、调整粗细和颜色。但有时你需要的图形并不在其中——通常是你自己的 logo 或某个特定领域的图标。解决方法是自己制作一个行为完全一致的符号:随 Dynamic Type 缩放,响应 .foregroundColor,随系统字体切换粗细。以下是完整的制作流程。

SF Symbols 的特别之处不在于它们是矢量图——而在于它们与系统字体是关联索引的。当用户选择 XL Dynamic Type 字号时,每个系统符号都会随之缩放。当你切换到粗体字重时,符号的笔画也会相应加粗。你的自定义符号也能做到这些,但前提是你必须以正确的模板格式提供它,并将其作为"Symbol Image"导入资产目录——而不是随意放一个 SVG 文件。

你将学到

第一步:建立心智模型

1

它是 SVG,但有必须遵守的图层 ID 和参考线

"自定义符号" SVG 是一个包含特定图层 ID、三条水平参考线,以及(通常)九个预绘制变体的 SVG 文件——三种尺寸(Small、Regular、Large)× 三种字重(Ultralight、Regular、Black)。SF Symbols 应用要求文件严格遵循这一结构,Xcode 的"Symbol Image"资产类型也知道如何读取它。

你不需要从头绘制全部九个变体。标准流程如下:

  1. 在系统符号中找一个与目标形状相近的符号。
  2. 从 SF Symbols 应用将其导出为模板——这会给你一个已包含所有 ID 和参考线的 SVG 脚手架。
  3. 在每个变体中替换图形内容(如果不需要完整集合,只替换一个也行)。
  4. 保存并拖入资产目录。

完成后,你的自定义符号就能像系统符号一样使用——在 SwiftUI 中用 Image("custom-name"),用 .font(.title) 缩放,用 .foregroundStyle(.red) 上色。

第二步:从 SF Symbols.app 获取模板

2

导出一个相似符号作为起点

打开 SF Symbols 应用(Apple 免费提供)。找到一个形状和比例与你想绘制的内容相近的系统符号,右键点击并选择 Export Symbol…——弹出的对话框会询问保存位置以及模板版本(选择你的最低系统版本所支持的最新版本)。

导出的文件可以在任何矢量工具中打开——Figma、Illustrator、Sketch,甚至 Inkscape。你会看到:

  • 三行(从上到下):Small、Regular、Large 尺寸变体
  • 三列(从左到右):Ultralight、Regular、Black 字重变体
  • 每个字形上的三条水平参考线:Cap Height(大写字高)、Baseline(基线)、Descender(下行线)——借鉴自字体排印学

这些参考线非常重要。它们决定了你的符号与周围文字并排时的对齐方式。如果字形的垂直范围不符合参考线,符号放在文字旁边时就会显得错位。

你不必绘制全部九个变体。最少只需要一个——中央的"Regular Regular"格子。Xcode 会通过缩放推导 Small/Large,并在 Ultralight/Black 中复用你的 Regular。绘制全部九个效果最佳,但对于内部工具或 v0 版本,一个就够了。
需要起始字形?试试聊天图像生成。 LingCode 的聊天内置了 generate_image 工具,接入了 Gemini。你可以发出指令:"生成一张 1024×1024 的单色图形:程式化的罗盘玫瑰,黑色背景透明,适合用作图标",助手会把结果保存到 <project>/assets/。输出的图片还不是模板格式,但它能给你一个干净的参考形状,供你在 Figma 中描摹,或直接作为第 4 步的源图导入 AI 的提示词。把它当作草图工具,而非最终资产。

第三步:替换图形内容

3

换掉字形,但不要动 ID 或参考线

在你的矢量工具中,选中中央的"Regular Regular"字形并替换为你的图形。注意以下限制:

  • 不要移动或重命名字形格子以外的图层。 SymbolsNotesGuides 以及变体格子的名称是 SF Symbols 导入器识别的关键,重命名会导致导入失败。
  • 字形的视觉主体应保持在 Cap Height 和 Baseline 参考线之间。任何延伸到 Baseline 以下的部分(如下行笔画)需要落在 Descender 参考线以上。
  • 使用描边或填充路径,不要随意混用。.symbolRenderingMode(.hierarchical) 渲染模式下,路径按图层顺序上色;如果形状不一致,颜色就会落在错误的位置。

对于其他变体:将 Regular 格子复制到 Small 和 Large 中(Xcode 本来就会从中央格子缩放,但提供预缩放版本能获得更清晰的效果)。如果时间允许,将 Regular 复制到 Ultralight(更细的笔画)和 Black(更粗的笔画)。如果没时间,留空也没关系,Xcode 会回退到 Regular 字重。

第四步:让 AI 助手生成模板

4

如果你已有 logo SVG,这比手动编辑快得多

如果你的 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 的比例不符合字体字形的比例——把资产目录预览的截图粘贴回去,让它调整缩放比例或垂直位置。

第五步:在 SwiftUI 中使用

5

只有一个参数不同——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(带有 .svg 扩展名的 PNG 也算)、模板中缺少图层 ID,或者资产目录条目是普通的 Image Set 而非 Symbol Image Set。删除该条目,重新拖入 SVG——Xcode 的"New Symbol Image Set"会创建正确的条目类型。如果你是通过"New Image Set"添加的,那就进错了地方。

第六步:何时用自定义符号,何时用普通图片

6

经验法则:它会紧挨着文字出现吗?

以下情况值得使用自定义符号的开销:

  • 图形需要与文字内联——按钮、列表行、导航项、徽章。Dynamic Type 缩放在这里很重要。
  • 需要匹配系统字体的字重——粗体标题旁边不应该有一个 Regular 字重的图标。
  • 希望它能自动响应 .foregroundStyle,而不是为不同颜色分别维护多个变体。

以下情况可以跳过自定义符号流程,直接使用普通矢量图或 PNG:

  • 图片尺寸大且独立展示——引导页的主视觉、空状态插图、启动页内容。符号是为内联使用设计的,在大尺寸下会显得单薄无力。
  • 需要多种固有颜色,且这些颜色不符合符号渲染模式(hierarchical、palette、multicolor)。对于始终是特定渐变的品牌标识,直接提供 PDF 资产即可。
  • 不需要 Dynamic Type 缩放。固定尺寸的产品图片无法从符号语义中获益。

接下来