刚进新团队那几天,我习惯先把Xcode的默认文件模板改了。原因很简单:新建一个类,顶部的注释还是上一任开发者的姓名和邮箱,日期停在半年前,版权行挂着某个完全不相关团队的名字。这事儿不大,但每次看到都膈应得慌,尤其当你准备把项目推到公共仓库或者交付给甲方时。修改Xcode源代码顶部的注释内容,本质上就是动Xcode新建文件时套用的那套模板,让Swift和Objective-C文件不再按系统默认格式“签字”,改成我们自己的作者、日期和项目描述。这篇文章把定位模板、改注释头、占位符原理、升级防覆盖这几个点一次性讲透,适合被默认模板烦到的iOS开发新人,也适合想给团队统一代码规范的负责人。
1. 为什么需要动模板注释:几个逃不掉的实际场景
1.1 新人入职第一天,打开Xcode就被模板吓到
说个最常见的情况:公司给新人配的电脑是上一任开发留下的,或者你在公共开发机上临时建了个分支,一新建类文件,抬头赫然写着别人的名字。这时候你面临两个选择:要么忍着,每次手动删;要么把整个模板换成自己的。手动删一次两次还行,但每天要新建十几个View、Model、Cell,每删一次都要多按几下Delete,效率损失不大,恶心程度极高。
更麻烦的是,如果公司项目里文件名带前缀、注释格式有统一规范,系统默认模板完全不匹配。默认的“Created by XXX on date”里,XXX通常是Mac系统的用户短名称,新人拿到手时显示的可能是上一任的账号名。当代码评审人看到注释里的名字和实际提交者不一致,追问起来又是一通解释。与其这样,不如一开始就把注释改成自己或团队的统一格式。
1.2 模板注释引起的版权隐患与代码洁癖
有些项目要对外开源、要交源码给客户,最怕的就是文件头残留上一家公司的版权声明。系统模板生成的那行“Copyright 年份 某公司 All rights reserved”看起来人畜无害,但真到了法务审核环节,一个过期的版权行可能引发不必要的误会。我见过有项目因为重构代码时把旧模板直接搬过来,上线后被原公司发函要求删除相关标识,虽然最后是误会,但中间沟通成本非常不值得。
还有一类人是纯代码洁癖。他们看不了注释里既有空格又有Tab、日期格式一会儿斜杠一会儿横杠。哪怕不影响编译,心里就是不舒坦。这类人改模板不是出于什么宏大理由,就是想让新建出来的文件干净整洁,一眼看过去舒服。说实话,我现在也属于这种人,改模板与其说是功能需求,不如说是审美需求。
1.3 一句话结论:模板注释是Xcode在替你“签字画押”
简单理解,Xcode新建文件时并不是纯创建一个空文件,它会从系统自带的模板目录里拷贝一个模板文件,然后把里面的占位符替换成当前用户、当前日期、当前项目名。你在工程里看到的这个注释头,就是模板里的占位符被替换后的结果。所以想改注释内容,就得找到那些模板源文件,把固定的模板头改掉,或者把占位符改成自己的固定信息。
明白这个机制之后,修起来就有的放矢了。下面先讲三个底层知识点,把这些搞懂,后面实操不会走弯路。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 修改前必须搞懂的三个底层知识点
2.1 Xcode文件模板到底藏在哪里
Xcode自带的文件模板分两个层级。第一层是系统级,存在Xcode应用包内部,路径大致是:
bash复制/Applications/Xcode.app/Contents/Developer/Library/Xcode/Templates/File Templates/
这里面按语言和用途分成好几个子目录,比如Source、Cocoa Touch、User Interface等。我们日常新建的Swift File、Cocoa Touch Class,对应的就是Source和Cocoa Touch里的模板包。第二层是用户级,路径在:
bash复制~/Library/Developer/Xcode/Templates/File Templates/
这个目录默认不存在,需要自己创建。Xcode在新建文件时,会优先扫描用户级目录,所以把自定义模板放这里,可以覆盖同名系统模板,而且Xcode升级时不容易被重置。这一点我后面第四部分会细说。
找路径有个很实用的技巧,用终端命令定位,不用在Finder里一层层点:
bash复制find /Applications/Xcode.app -type d -name "*.xctemplate" -maxdepth 10 2>/dev/null
也可以直接cd进去看目录。注意有些模板藏在平台的子目录里,比如经典老路径:
bash复制/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Templates/
如果你在根路径找不到某个模板,去平台目录里翻一下。近几年Xcode把大多数路径都收敛到了统一版本,但保险起见用find命令全盘搜一遍最稳。
2.2 TemplateInfo.plist 与物理模板文件是两回事
每个模板包(.xctemplate目录)里通常包含两类东西:一个是名为TemplateInfo.plist的配置文件,另一个是一堆模板文件,常见名字是:
___FILEBASENAME___.h___FILEBASENAME___.m___FILEBASENAME___.swift
很多人第一次去改模板,会打开TemplateInfo.plist,看到里面有一堆Description、AllowedTypes、Options字段,以为注释内容在里面,结果翻了半天也没找到Copyright字样。其实TemplateInfo.plist负责的是向导界面和文件行为,也就是你点击“新建文件”时弹出对话框里显示的选项、默认文件名等。真正决定文件顶部注释长啥样的是那些物理模板文件。
举个例子,Cocoa Touch Class模板包里有个 ___FILEBASENAME___.h,这个文件里的内容会被Xcode当作新头文件的初始内容,里面的 ___FILEHEADER___占位符则会被展开成一段完整的注释头。我们从上往下看模板文件,就能看到这段注释头长什么样。
这里容易犯的错是:只改plist,不改模板文件,结果新建文件模板向导变了,文件头还是老的。反过来,只改模板文件不动plist也能生效。所以核心思路应该是“模板文件为主,plist为辅”。
2.3 模板变量:那些带下划线的占位符是什么
模板文件里有一堆奇奇怪怪的占位符,比如 ___FILEBASENAME___、___FULLUSERNAME___、___DATE___、___COPYRIGHT___。这些变量会在Xcode生成文件时被替换成实际值。我整理一份常用的速查表:
| 占位符 | 替换值 | 示例 |
|---|---|---|
___FILEBASENAME___ |
新建文件名(不含扩展名) | MyViewController |
___FILENAME___ |
完整文件名 | MyViewController.swift |
___PROJECTNAME___ |
当前项目名 | DemoApp |
___FULLUSERNAME___ |
当前系统用户的全名 | zhangsan |
___DATE___ |
当前日期 | 2025/04/01 |
___YEAR___ |
当前年份 | 2025 |
___COPYRIGHT___ |
完整的版权声明行 | Copyright © 2025 xxx. All rights reserved. |
___ORGANIZATIONNAME___ |
组织名称 | xxx Inc. |
这些不是神秘的宏定义,Xcode在文件生成阶段做字符串替换。替换完之后,占位符不会再存在于你的源码里。所以如果你想在注释里固定写死某个名字,直接写成文本就行;如果你想跟着系统变,就保留占位符。
有一点要提醒:___COPYRIGHT___这个占位符展开后的内容,受项目或Target里的Organization Name影响。如果工程里没配置,它可能就是“Copyright © 2025”加上当前用户名。改模板最直接的办法是干脆不依赖它,自己把版权行写死在模板文件里,或者只保留年份变量,这样可控性更强。
3. 实操:把自己的签名写进Xcode默认注释
3.1 第一步:定位模板目录(含命令行辅助)
我一般不建议直接去改系统目录里的模板,风险在于Xcode升级会覆盖,而且权限操作容易把系统文件搞乱。更稳的做法是在用户目录建一套自己的模板目录。先创建:
bash复制mkdir -p ~/Library/Developer/Xcode/Templates/File Templates/Custom
然后把系统模板复制过来改。定位系统模板的位置刚才说过,用find搜。假设要复制Cocoa Touch Class模板,命令可以这样:
bash复制find /Applications/Xcode.app -type d -name "Cocoa Touch Class.xctemplate" -exec cp -R {} ~/Library/Developer/Xcode/Templates/File Templates/Custom/ \;
执行完,在用户目录的Custom下就应该出现一个Cocoa Touch Class.xctemplate。这之后我们改的是这个副本,系统里的原版不受影响。新建文件时,用户级目录里的模板会显示在Xcode模板选择器里。
如果你是第一次操作,建议先在Terminal里把目录打开看一眼结构:
bash复制open ~/Library/Developer/Xcode/Templates/File\ Templates/Custom/Cocoa\ Touch\ Class.xctemplate/
看到里面的TemplateInfo.plist和 ___FILEBASENAME___.h、___FILEBASENAME___.m 等文件,说明路径对了。
3.2 第二步:改 Objective-C 类模板的注释头
Objective-C的类模板里,注释头部主要写在两个文件中:___FILEBASENAME___.h 和 ___FILEBASENAME___.m。这两个文件内容结构很像,用文本编辑器打开后,默认你会看到类似这样的模板内容:
objc复制//
// ___FILENAME___
// ___PROJECTNAME___
//
// Created by ___FULLUSERNAME___ on ___DATE___.
// Copyright ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
//
#import <UIKit/UIKit.h>
注意这里的注释块是 // 风格,不是 /* */ 风格。要把注释头改成自己的,直接替换这几行文本。比如改成:
objc复制//
// ___FILENAME___
// ___PROJECTNAME___
//
// Created by 张三 on ___DATE___.
// Copyright © ___YEAR___ 某团队. All rights reserved.
//
如果想要更精简,也可以直接去掉Created和Copyright那两行,只保留文件名和项目名。比如:
objc复制//
// ___FILENAME___
// ___PROJECTNAME___
//
修改完记得 .h 和 .m 两个文件都要改,因为新建一个类时Xcode会同时生成两个文件,两者顶部注释都来自各自的模板文件。如果你只想让Swift文件变,那就去改对应的Swift模板,别动Objective-C的。
还有类扩展、Category、Protocol这些不同类型的模板,注释头可能写在不一样的文件里,但套路完全一致。打开对应模板目录下的物理文件,找到注释段,改,保存。
3.3 第三步:改 Swift 文件模板的注释头
Swift文件的顶部注释和Objective-C类似,系统默认模板一般是这样的:
swift复制//
// ___FILENAME___
// ___PROJECTNAME___
//
// Created by ___FULLUSERNAME___ on ___DATE___.
// Copyright ___YEAR___ ___ORGANIZATIONNAME___. All rights reserved.
//
import UIKit
这个模板一般出现在两种地方:一是Cocoa Touch Class模板里的Swift变体(新建类时语言选Swift),二是独立的Swift File模板。如果你改完Cocoa Touch Class后发现新建纯Swift File时还是旧注释,那就是没改到Swift File模板,两个地方都要处理。
我习惯把这部分改成:
swift复制//
// ___FILENAME___
//
// 项目名: ___PROJECTNAME___
// 描述: 这里填写类的功能描述
// 作者: 张三
// 日期: ___DATE___
//
这个格式的好处是信息全,而且不依赖 ___COPYRIGHT___ 这种受系统配置影响的变量,稳定。注意注释里用了中文,Xcode对UTF-8文件没任何问题,模板源文件保存成UTF-8编码即可。
改模板文件时有个细节:Swift文件和Objective-C文件一样,模板源文件顶部的注释本身也是模板的一部分。如果你在顶部加一个空行,那么新建出来的每个文件都会多一个空行,可能会触发团队代码规范的警告。所以改完模板后,务必新建一个临时文件看一眼实际效果。
3.4 第四步:让改动对所有新文件生效
改完模板后,需要重启Xcode才能让它重新扫描模板目录。有时候不用重启,新建文件时模板选择器里会出现,但为了保险,我习惯先退出Xcode再重开。操作顺序是:改完用户模板 → 完全退出Xcode(Cmd+Q)→ 重新打开项目 → 新建一个文件测试。
验证时新建一个类,类名随意,比如TestViewController。打开生成的 TestViewController.swift,看顶部注释是不是你刚刚写的格式。如果还是老的,大概率是系统模板目录优先于用户目录被读取了,或者你没有把模板放进正确的分类路径下。这个问题我放在后面常见问题里专门讲。
到这里,基本修改已经完成。如果你只是给自己电脑用,内容到此就够了。但如果你想让一套注释模板在一个团队里通用、并且在Xcode升级之后不丢,最好再看看下面的进阶方案。
4. 进阶玩法:自定义团队级模板,不再怕Xcode升级
4.1 复制一份自定义模板并注册
系统模板最大的问题是升级即失效。每次Xcode大版本更新,Xcode.app内部的模板目录会被整体替换,你之前辛辛苦苦改的注释头全部回到原点。解决办法就是把自己改好的模板完整挪到用户目录,让Xcode在扫描时优先生成自定义模板。
具体来说,把整个.xctemplate文件夹复制到 ~/Library/Developer/Xcode/Templates/File Templates/ 下,可以新建一个子目录分类,比如:
bash复制~/Library/Developer/Xcode/Templates/File Templates/Team/
这样Xcode新建文件向导里会多出一个Team分类,下面放着你自定义的类模板。团队内部协作时,把这个Team目录连同使用说明一起放进工程仓库的Scripts或Docs目录,其他人clone下来后执行一段拷贝脚本,或者手动放到用户目录,就能统一注释头。
这个方法比直接改系统模板优雅得多,因为你的模板和Xcode本体完全解耦。Xcode升级后系统模板再怎么变,用户目录里的自定义模板不受影响。唯一要注意的是模板分类名称如果和系统模板重名,可能产生两个同名入口,建议分类名取项目特色一点,比如“XXTeamFile”。
4.2 把日期、作者、项目名做成动态变量
有人会问:我不想把作者固定写死成张三,而是让每个开发者新建文件时自动带上自己的系统用户名,怎么做?其实保留 ___FULLUSERNAME___ 就行。这个变量读取的是当前登录用户的全名,每台电脑不同,所以“动态”它天然具备。
日期变量 ___DATE___ 同理,会在新建那一刻被替换成当天日期。这里有个坑:不同Xcode版本下 ___DATE___ 格式不完全一样,有的输出“2025/04/01”,有的输出“Apr 1, 2025”。如果你的团队有严格的日期格式要求,不要指望这个变量能稳定输出。更稳妥的做法是在模板里只留年份 ___YEAR___,或者干脆写死不写日期,让作者自己补。
项目名变量 ___PROJECTNAME___ 在多数情况下是准确的项目名。但遇到Xcode工作区包含多个工程、或者项目名和Target名不一致时,它可能取到你认为不合适的值。所以我的建议是:注释里最稳定的变量是 ___FILEBASENAME___ 和 ___YEAR___,其他变量都可以按需写死。模板越依赖变量,越容易在不同工程里产生不一致的效果。
4.3 模板内细节:缩进、空行和换行的坑
这是个人最容易踩的细节坑。模板文件里所有的缩进、空行、Tab、空格都会被原样复制到新文件里,所以你在编辑模板时必须格外小心。
第一,文件顶部不要有BOM头。用Xcode、VS Code或vim保存UTF-8编码时,不要选“带BOM”的选项。BOM头一旦出现,新建的Swift文件第一行会多一个肉眼看不见的字符,在某些工具链里会报错或显示异常。
第二,换行符尽量用LF,不要用CRLF。Windows上编辑过后再拷到Mac上,模板文件如果变成CRLF,Xcode解析一般也能扛住,但和你工程里其他文件的换行风格不一致,混在一起看起来非常糟心。macOS平台上新建文件默认用LF,模板里的换行要跟随这个习惯。
第三,注释头的空行数量会影响文件顶部留白。如果你在模板注释块和 import UIKit 之间保留两个空行,新文件里就会有两个空行。很多代码规范要求文件头注释和import之间最多一个空行,请按这个标准设置模板。
第四,模板文件名里的 ___FILEBASENAME___ 不能改动大小写和三个下划线。这个占位符承担了注入新文件名的任务,一旦写错,新建出来的文件名就会变成字面量 ___FILEBASENAME___,非常尴尬。
5. 常见问题与排查技巧实录
5.1 修改完为何新文件顶部注释纹丝不动
这是被问得最多的问题。改完模板后,新建文件抬头还是“Created by 旧名字”,八成原因是你改错了文件。
排查思路如下:先确认你改的是不是当前用到的那套模板。举例,你平时新建ViewController用的是Cocoa Touch Class模板,但你改的是Source下的Swift File模板,自然不生效。同一个类模板内部可能还有Base类、Subclass等多个变体,模板包里存在多个物理模板文件,分别对应不同选项,光改一个文件是不够的。
另一个经典原因是改完没重启Xcode。模板目录在Xcode启动时被扫描,不重启就不会重新读取。别问我为什么,实测下来重启之后才能稳定看到改动,除非你用的是用户级模板并且恰好触发了动态读取。
还有一个原因是权限问题。如果直接改了系统目录下的模板,但当前用户对该文件没有写权限,保存时系统可能生成了一个副本或直接静默失败。建议检查模板文件修改时间,确认确实保存成功。
5.2 Xcode升级后模板被重置
大版本升级把系统模板覆盖掉,这是系统级模板的宿命。解决方式上面提过,就是把自定义模板放到用户级目录。如果模板已经放在用户目录,升级后依然出现老模板,请检查Xcode新建文件向导的左侧列表,看是否同时存在两个同名模板。如果有一个是你的Team分类,手动选择Team分类下的模板即可。
这里补充一个技巧:把自定义模板目录作为Git仓库管理,升级后即使丢了,也可以一条命令恢复。我是在公司内部分享模板时用了一个简单脚本,脚本内容大致是拷贝文件加输出提示,同事跑完重启Xcode就能用,比人工拖文件夹省事很多。
5.3 命令行创建的源代码文件不生效
Xcode模板只在Xcode IDE新建文件时被读取。如果你在命令行用 touch、echo 或者脚本工具生成 .swift 文件,那些文件显然不会自动带上Xcode模板头。这不是你操作有问题,而是机制如此。
想要命令行创建的源文件也带统一注释,可以用 swift 包管理工具或其他脚手架生成器来做,但那已经超出“修改Xcode模板”的范畴了。我个人的建议是:如果团队里大量用命令行生成代码,就单独写一个生成脚本,把注释头以字符串形式先写入文件,再追加业务代码模板。这样命令行环境和Xcode IDE环境都能统一。
5.4 不同Xcode版本下模板目录不一致
老版本的Xcode把模板放在平台子目录里,新版本收敛到了统一目录。不同电脑上路径有差异,这是排查模板修改无效时最容易忽略的问题。如果你在一台电脑上成功修改了方法,到另一台电脑上发现找不到对应目录,很大概率是版本差异。
最稳的做法不是记路径,而是用find命令全局搜。我在前面已经给过命令,用模板名去搜索,不管它在哪一层,都能找到。找到后先打开目录结构,确认是哪一个模板包,再决定是复制还是原地修改。千万别凭经验手敲路径。
还有一个小坑:模板包名字里的空格。剪切板复制路径时如果路径里有空格,终端命令需要转义,比如 Cocoa\ Touch\ Class.xctemplate。用引号括起来更安全:
bash复制cp -R "/Applications/Xcode.app/Contents/Developer/Library/Xcode/Templates/File Templates/Source/Cocoa Touch Class.xctemplate" ~/Library/Developer/Xcode/Templates/File Templates/
我刚开始的时候就因为漏掉转义,命令报找不到路径,排查了半天才反应过来是空格问题,写在这里给大家提个醒。
实际操作中的一点体会
改模板这件事看起来小,但它能直接影响团队代码风格和交付安全。我个人在这件事上的习惯是:永远不动系统模板,永远保持一份用户级自定义模板,并把它纳入版本管理。改完模板后一定新建一个空类文件验证,眼见为实。还有个小建议,注释头别写得太满,文件名、项目名、作者、日期够了就行,版权信息如果需要保留,放在固定位置不要用受系统设置影响的变量。这样后续接手项目的人看到的就是一套干净、稳定、可预期的文件头,而不是每个人建出来的文件都长得不一样。
