本篇目标

掌握 SwiftUI 表单与输入组件,包括 TextField、SecureField、Toggle、Picker、Stepper、Slider、DatePicker,能构建带表单验证与数据绑定的完整输入界面。

一、Form 表单容器

Form 是专门用于收集用户输入的容器,自动应用分组样式。

Form {
    Text("第一项")
    Text("第二项")
}

带分区:

Form {
    Section("账户") {
        Text("用户名")
        Text("邮箱")
    }

    Section("设置") {
        Text("通知")
        Text("隐私")
    }
}

特点:

  • 自动适配 iOS 设置页风格。

  • 支持 Section 分组。

  • 内部组件自动对齐。

  • 适合设置页、编辑页、注册页。

二、TextField 文本输入

基础用法:

@State private var name = ""

TextField("请输入名字", text: $name)

带标题:

TextField("用户名", text: $username)
    .textFieldStyle(.roundedBorder)

常用输入样式:

样式

说明

.automatic

默认

.roundedBorder

圆角边框

.plain

无样式

键盘类型:

TextField("邮箱", text: $email)
    .keyboardType(.emailAddress)

TextField("电话", text: $phone)
    .keyboardType(.phonePad)

TextField("数字", text: $number)
    .keyboardType(.numberPad)

TextField("网址", text: $url)
    .keyboardType(.URL)

自动大写与纠错:

TextField("用户名", text: $username)
    .textInputAutocapitalization(.never)
    .autocorrectionDisabled()

提交动作:

TextField("搜索", text: $query)
    .onSubmit {
        print("搜索:\(query)")
    }

多行文本:

TextField("描述", text: $description, axis: .vertical)
    .lineLimit(3...6)

三、SecureField 密码输入

@State private var password = ""

SecureField("密码", text: $password)

特点:

  • 输入内容以圆点显示。

  • 适合密码、验证码等敏感信息。

  • 用法与 TextField 相同。

带边框:

SecureField("密码", text: $password)
    .textFieldStyle(.roundedBorder)

四、Toggle 开关

@State private var isOn = false

Toggle("启用通知", isOn: $isOn)

自定义标签:

Toggle(isOn: $isOn) {
    VStack(alignment: .leading) {
        Text("启用通知")
        Text("接收最新消息")
            .font(.caption)
            .foregroundColor(.gray)
    }
}

开关颜色:

Toggle("启用", isOn: $isOn)
    .tint(.green)

五、Picker 选择器

分段选择:

@State private var selected = 0

Picker("选择", selection: $selected) {
    Text("选项一").tag(0)
    Text("选项二").tag(1)
    Text("选项三").tag(2)
}
.pickerStyle(.segmented)

菜单选择:

Picker("排序方式", selection: $sortBy) {
    Text("名称").tag("name")
    Text("时间").tag("date")
    Text("热度").tag("popular")
}

滚轮选择:

Picker("选择", selection: $selected) {
    ForEach(0..<10) { index in
        Text("第 \(index) 项").tag(index)
    }
}
.pickerStyle(.wheel)

常用样式:

样式

说明

.automatic

自动

.segmented

分段

.wheel

滚轮

.menu

菜单

.inline

内联

六、Stepper 步进器

@State private var count = 0

Stepper("数量:\(count)", value: $count)

设置范围:

Stepper("数量:\(count)", value: $count, in: 1...10)

设置步长:

Stepper("数量:\(count)", value: $count, in: 0...100, step: 5)

自定义标签:

Stepper(value: $count, in: 0...10) {
    HStack {
        Text("数量")
        Spacer()
        Text("\(count)")
            .foregroundColor(.gray)
    }
}

七、Slider 滑块

@State private var value = 0.5

Slider(value: $value)

设置范围:

Slider(value: $value, in: 0...100)

设置步长:

Slider(value: $value, in: 0...100, step: 10)

带标签:

Slider(value: $value, in: 0...100) {
    Text("音量")
}

显示当前值:

VStack {
    Slider(value: $value, in: 0...100)
    Text("当前值:\(Int(value))")
        .font(.caption)
        .foregroundColor(.gray)
}

八、DatePicker 日期选择

@State private var date = Date()

DatePicker("选择日期", selection: $date)

日期与时间:

DatePicker("时间", selection: $date, displayedComponents: .hourAndMinute)
DatePicker("日期", selection: $date, displayedComponents: .date)
DatePicker("日期和时间", selection: $date, displayedComponents: [.date, .hourAndMinute])

样式:

DatePicker("日期", selection: $date, displayedComponents: .date)
    .datePickerStyle(.graphical)

常用样式:

样式

说明

.automatic

自动

.compact

紧凑

.wheel

滚轮

.graphical

图形日历

设置范围:

DatePicker("日期", selection: $date, in: Date()...)

九、表单验证

基础验证:

struct RegisterView: View {
    @State private var username = ""
    @State private var email = ""
    @State private var password = ""

    var isFormValid: Bool {
        !username.isEmpty &&
        email.contains("@") &&
        password.count >= 6
    }

    var body: some View {
        Form {
            Section("账户信息") {
                TextField("用户名", text: $username)
                TextField("邮箱", text: $email)
                    .keyboardType(.emailAddress)
                    .textInputAutocapitalization(.never)
                SecureField("密码(至少 6 位)", text: $password)
            }

            Section {
                Button("注册") {
                    // 注册操作
                }
                .disabled(!isFormValid)
            }
        }
    }
}

实时错误提示:

if !email.isEmpty && !email.contains("@") {
    Text("邮箱格式不正确")
        .font(.caption)
        .foregroundColor(.red)
}

十、综合示例:设置页

struct SettingsView: View {
    @State private var username = ""
    @State private var notificationsOn = true
    @State private var theme = 0
    @State private var fontSize = 14.0
    @State private var dailyGoal = 5
    @State private var reminderDate = Date()

    var body: some View {
        Form {
            Section("账户") {
                TextField("用户名", text: $username)
            }

            Section("通知") {
                Toggle("启用通知", isOn: $notificationsOn)

                if notificationsOn {
                    DatePicker("提醒时间", selection: $reminderDate, displayedComponents: .hourAndMinute)
                }
            }

            Section("外观") {
                Picker("主题", selection: $theme) {
                    Text("浅色").tag(0)
                    Text("深色").tag(1)
                    Text("跟随系统").tag(2)
                }
                .pickerStyle(.segmented)

                VStack(alignment: .leading) {
                    Text("字号:\(Int(fontSize))")
                        .font(.caption)
                    Slider(value: $fontSize, in: 12...24, step: 1)
                }
            }

            Section("目标") {
                Stepper("每日目标:\(dailyGoal)", value: $dailyGoal, in: 1...20)
            }
        }
        .navigationTitle("设置")
    }
}

十一、避坑指南

  • TextField 绑定需要 @State:否则无法输入。

  • SecureField 不要存储明文密码:真实项目应加密。

  • Picker 的 tag 必须匹配 selection 类型:否则选中无效。

  • Form 内 Section 标题用字符串:不要嵌套复杂视图。

  • 键盘遮挡输入框:注意滚动或使用 ScrollView。

  • 表单验证实时性:可以实时提示,但不要过于激进。

  • @FocusState 管理焦点:多输入框时建议使用。

十二、检查清单

  • [ ] 会使用 Form 与 Section

  • [ ] 掌握 TextField 与 SecureField

  • [ ] 会使用 Toggle、Picker、Stepper、Slider

  • [ ] 会使用 DatePicker

  • [ ] 能实现基础表单验证

  • [ ] 能构建完整设置页

  • [ ] 理解 @State 与输入的绑定