从新建文件开始:先搭好练习入口
在开始写按钮示例之前,先在现有项目里添加一个新的 SwiftUI 文件。Xcode 顶部菜单路径是 File > New > File form Template...,快捷键是 ⌘ + N。
这里创建一个名为 ButtonBootcamp.swift 的文件,后面的示例都可以放在这个文件里练习。本文会按 3 个问题展开:Button 怎么写、内置样式怎么切换、常见进阶能力怎么用。
Button 的基本写法有哪些
SwiftUI 里的 Button 最常见有两种初始化方式:一种直接传入标题文本,另一种使用自定义 label 视图。前者适合快速创建简单按钮,后者更适合后续接图标、图片或自定义布局。

VStack {
// 使用文本标题进行初始化按钮
Button("点击我!") {
print("按钮被点击了!")
}
// 使用自定义视图进行初始化按钮
// 例如图标和文字组合、图片等,便于更灵活地定义按钮内容:
Button {
print("按钮被点击了!")
} label: {
Text("点击我!")
}
}
如果你只是想快速响应点击事件,直接传标题即可;如果你已经预见按钮内容会扩展,建议优先使用 label 写法,后面改造成本更低。
SwiftUI 内置按钮样式怎么选
SwiftUI 自带几种常用按钮样式,足够覆盖不少基础界面需求。它们的区别主要体现在背景、边框和交互视觉上,适合先用系统能力把结构搭起来,再考虑是否需要完全自定义。

PlainButtonStyle:去掉背景,保留按钮行为
PlainButtonStyle 会移除默认背景效果,让按钮看起来更接近普通文本视图。
// 文本样式按钮效果
Button("点击我!") {
print("按钮被点击了!")
}
.buttonStyle(PlainButtonStyle())
// 另一种方式
//.buttonStyle(.plain)
如果你在 iPhone 预览里感觉区别不明显,不一定是代码没生效,而是 SwiftUI 在手机端对组件样式做了一定优化。原文提到可以切换到 macOS 端预览观察效果;在这种情况下,默认按钮通常会带颜色背景,而 .plain 样式不会。
如果你的项目里没有 My Mac 选项,可以先按项目配置补上,再查看对应预览效果。
BorderlessButtonStyle:适合列表等轻量交互
BorderlessButtonStyle 通常用于列表中的按钮,它不会强调背景效果,整体观感和纯文本样式比较接近,但语义上仍然是按钮。
Button("无边框样式") {
print("按钮被点击了")
}
.buttonStyle(BorderlessButtonStyle())
// 另一种写法
//.buttonStyle(.borderless)
BorderedButtonStyle:iOS 15 与 macOS 12 新增边框样式
BorderedButtonStyle 是在 iOS 15 和 macOS 12 中新增的样式,按钮会带有更明显的边框,视觉上更接近标准操作按钮。
Button("边框样式") {
print("按钮被点击了")
}
.buttonStyle(BorderedButtonStyle())
//.buttonStyle(.bordered)
如果你希望保留系统按钮的明确可点击感,.bordered 会比纯文本样式更直接。原文作者提到,日常使用里自己更偏好文本样式,因为背景和视觉效果更方便手动定义,这也是很多项目里的常见做法。
几个常见进阶用法:禁用、图标和角色
掌握基础点击和样式后,Button 真正常用的能力主要集中在状态控制与语义表达上。下面这几项,是实际开发里很容易马上用到的内容。

如何禁用按钮:使用 .disabled
想控制按钮当前是否可点击,可以直接使用 .disabled。
@State private var isDisabled = true
Button("禁用按钮") {
print("按钮被点击了")
}
.disabled(isDisabled)
这里的关键点不只是 .disabled(isDisabled),还包括前面的 @State。原文对它的解释是:它用于在当前视图环境中存储值,这个值不会因为视图刷新而重新初始化,从而避免状态被反复重置。
也就是说,使用 @State 定义的变量只会在当前视图首次加载时初始化,后续视图刷新不会重复初始化。这正是它适合驱动按钮启用/禁用状态的原因。
如何做带图标的按钮
如果按钮不只是文字,而是需要文字加图标,可以直接在按钮内容里使用 Label。
Button(action: {
print("带图标的按钮被点击了")
}) {
Label("收藏", systemImage: "star.fill")
}
这种写法适合“收藏”“分享”“编辑”这类有明确图标语义的操作,比单独写文本更容易被用户快速识别。
ButtonRole 有什么用
从 iOS 15 开始,SwiftUI 引入了 ButtonRole 参数,可以给按钮增加更明确的语义角色,比如 .destructive 和 .cancel。
Button("删除", role: .destructive) {
print("删除按钮被点击了")
}
.destructive 用于危险操作,例如删除;.cancel 用于取消操作,常见于弹窗或操作表中。
这一能力的重点并不是“按钮自动拥有了某种业务逻辑”,而是“按钮拥有了更清晰的语义”。比如 .destructive 表示这是一个危险或不可逆的操作,典型场景包括“删除”“重置”“清空数据”等。SwiftUI 会依据系统风格,为它提供红色字体或强调样式,提醒用户这个动作可能带来数据丢失或其他明显影响。
需要注意的是,给按钮设置角色,主要是帮助你表达视觉和语义上的意图,SwiftUI 并不会自动给这个按钮附加对应功能。是否真的删除、取消,仍然取决于你在按钮动作里写了什么代码。
预览与使用建议:什么时候用哪一种
完成这些示例后,可以把预览视图切回手机端,再看一遍实际效果。这样你会更容易判断:哪些样式在 iPhone 上差异明显,哪些更适合在 macOS 预览里观察。
如果你是刚开始用 SwiftUI 的 Button,可以先记住这几个判断:
- 只做简单点击,用最基础的标题初始化就够了。
- 按钮内容可能扩展成图标、图片或组合视图时,优先用
label写法。 - 希望保留系统外观时,优先考虑内置样式;希望完全掌控视觉时,
.plain往往更方便继续自定义。 - 涉及是否可点击的交互状态,用
.disabled配合@State管理。 - 涉及删除、取消这类动作时,用
ButtonRole先把语义表达清楚。
到这里,这一节关于 SwiftUI Button 的基础能力就比较完整了:包括基本使用、内置样式切换、按钮禁用、图标按钮和角色语义,已经足够覆盖多数入门与日常页面开发场景。













