UITextField 是 UIKit 中用于 iOS 单行文本输入的标准组件,继承自 UIControl 并支持广泛的键盘模式。根据 Apple Developer (2025) 文档,UITextField 提供 UITextFieldDelegate 委托,包含 shouldBeginEditing、shouldChangeCharactersInRange 和 shouldReturn 回调。与 UITextView 不同,UITextField 将输入限制为单行,并支持 secureTextEntry、leftView 和 rightView 用于自定义控件。这是 iOS 应用中登录、搜索、注册和数据输入表单的主要元素。
要点
UITextField 是 UIKit 框架中用于用户单行文本输入的类。该类继承自 UIControl,允许通过 target-action 机制订阅输入事件:addTarget(self, action: Selector("textChanged:"), for: editingChanged)。UITextField 显示边框 (borderStyle)、空字段时的占位文本、清除按钮 (clearButtonMode),并可包含左/右辅助视图。该字段在获得/失去焦点时通过 becomeFirstResponder 和 resignFirstResponder 自动显示/隐藏键盘。字段大小通过 intrinsicContentSize 基于字体和边框样式确定。要在 Interface Builder (Storyboard/XIB) 中创建 UITextField,请使用 Object Library,以编程方式则通过初始化器 UITextField(frame: CGRect)。该类完全兼容现代 iOS 架构:Combine publishers、SwiftUI 中通过 UIViewRepresentable 的 @Published 以及用于表单的 Diffable Data Source。
UITextField 通过 keyboardType 属性支持 12 种键盘类型。每种类型针对特定输入场景优化字符集。UIKeyboardType.default — 标准 QWERTY 键盘。UIKeyboardType.numberPad — 仅数字无额外字符(适合 PIN 码和电话号码)。UIKeyboardType.emailAddress — 主层带 @ 符号和句点的键盘。UIKeyboardType.URL — 主层带 .com、/ 和 . 的键盘。UIKeyboardType.phonePad — 带 +、*、# 用于输入电话号码的数字键盘。UIKeyboardType.decimalPad — 带小数点的数字键盘用于输入价格。UIKeyboardType.webSearch — 带 Go 按钮和优化搜索查询的键盘。UIKeyboardType.asciiCapable — 仅 ASCII 字符用于拉丁字母。键盘在调用 becomeFirstResponder 时显示,在 resignFirstResponder 时隐藏。键盘类型可在编辑过程中动态更改。
| 类型 | 场景 | 特点 |
|---|---|---|
| default | 通用文本输入 | 标准 QWERTY |
| numberPad | PIN,代码 | 仅数字 0-9 |
| emailAddress | 电子邮件 | @ 和 . 在主层 |
| URL | 网址 | .com、/、. 在主层 |
| phonePad | 电话 | 数字、+、*、# |
| decimalPad | 价格、数字 | 数字 + 小数点 |
UITextFieldDelegate 是一种协议,定义了文本字段在不同输入阶段的行为。主要方法:textFieldShouldBeginEditing(textField) — 返回 Bool,允许或禁止开始编辑;textFieldDidBeginEditing — 在键盘出现后调用;textFieldShouldEndEditing — 检查编辑是否可以结束(如为 false,字段不会失去焦点);textFieldDidEndEditing — 在键盘隐藏后调用;textFieldShouldChangeCharactersInRange — 在每个字符输入时调用,允许过滤输入(仅允许一个字符,如果返回 false — 字符不会添加);textFieldShouldReturn — 在按下 Return/Go/Next/Search 时调用,用于跳转到下一个字段。委托不是可选的:所有方法都有默认实现,但自定义行为需要重写相应的方法。
shouldReturn 方法 — 在表单字段之间导航的标准模式。实现:textFieldShouldReturn(textField) — 我们检查哪个 textField 触发了事件,并通过 becomeFirstResponder() 将焦点移到下一个字段。如果这是最后一个字段 — 我们调用 resignFirstResponder() 来隐藏键盘。要存储对字段的引用,请使用 IBOutlet collection 或每个字段单独的 IBOutlet。
isSecureTextEntry — UITextField 的属性,当为 true 时,将输入的字符替换为圆点 (•) 并阻止通过 UIMenuController 复制文本。用于密码、PIN、CVV 字段。在安全模式和普通文本之间切换时 (show/hide password),设置 textField.isSecureTextEntry.toggle()。重要提示:更改 isSecureTextEntry 时字段文本会重置 — 请预先保存。 LeftView 和 RightView — 是在输入字段左侧或右侧显示的自定义 UIView。典型用法:leftView 中的搜索图标,rightView 中的"清除"按钮。配置:textField.leftViewMode = always(始终)或 whileEditing(仅编辑时)。Left/right view 在文本字段内自动定位,考虑内边距。视图大小由 bounds 或 Auto Layout 确定。
import UIKit
class LoginViewController: UIViewController {
let passwordField = UITextField()
override func viewDidLoad() {
super.viewDidLoad()
passwordField.isSecureTextEntry = true
passwordField.placeholder = "Password"
passwordField.keyboardType = .asciiCapable
passwordField.delegate = self
// 自定义显示/隐藏密码按钮
let showButton = UIButton(type: .system)
showButton.setTitle("显示", for: .normal)
showButton.addTarget(self, action: #selector(togglePasswordVisibility),
for: .touchUpInside)
passwordField.rightView = showButton
passwordField.rightViewMode = .always
}
@objc func togglePasswordVisibility() {
passwordField.isSecureTextEntry.toggle()
}
}
UITextInputTraits 是一种协议,定义了 UITextField 键盘的视觉和行为调整。主要属性:autocorrectionType (.default, .no, .yes) — 开启或关闭文本自动更正;autocapitalizationType (.none, .words, .sentences, .allCharacters) — 首字符自动大写;spellCheckingType — 拼写检查;returnKeyType (.done, .go, .next, .search, .send, .continue, .join, .route, .emergencyCall) — 键盘上 Return 按钮的文本;enablesReturnKeyAutomatically — 字段为空时自动禁用 Return 按钮。对于名称输入字段使用 autocapitalizationType = .words,电子邮件使用 autocorrectionType = .no,URL 使用 keyboardType = .URL + autocapitalizationType = .none。Traits 的配置在字段初始化后、显示前进行。更改 traits 会在下次出现时动态更新键盘。
Return Key Type 确定键盘上按钮的文本:Next — 前往下一个字段,Done — 完成输入,Search — 开始搜索,Send — 提交表单,Continue — 继续填写。结合委托方法 shouldReturn,returnKeyType 可以创建自然的用户体验:用户填写字段,按 Next 转到下一个字段,在最后一个字段上按 Done 提交。要自定义按钮文本,请使用 iOS 15+ 中的 UIButtonConfiguration。
Placeholder UITextField — 是字段为空时以灰色显示的文本。配置:textField.placeholder = "Enter email"。要自定义 placeholder 的颜色和字体,请使用带有 NSAttributedString 的 attributedPlaceholder。输入掩码 通过委托方法 shouldChangeCharactersInRange 实现 — 支持电话号码、日期、信用卡、SNILS 格式。输入掩码允许分离显示和值:用户看到格式化文本(例如 +7 (999) 999-99-99),而模型中存储的是 "79999999999"。实现示例:将掩码存储为带有要替换的 X 符号的字符串;每次输入时创建格式化字符串并在 shouldChangeCharactersInRange 中返回 false,通过 textField.text = formattedText 替换字段文本。对于数字使用 NumberFormatter 和 decimal keyboardType。
extension LoginViewController: UITextFieldDelegate {
func textFieldShouldReturn(
textField: UITextField
) -> Bool {
if textField == emailField {
passwordField.becomeFirstResponder()
} else if textField == passwordField {
textField.resignFirstResponder()
loginTapped()
}
return true
}
func textField(
textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String
) -> Bool {
// 阻止电子邮件中的空格
if textField == emailField && string == " " {
return false
}
// 密码长度限制
if textField == passwordField {
let newLength = (textField.text?.count ?? 0) +
string.count - range.length
return newLength <= 32
}
return true
}
}
让我们来看一个完整的登录表单实现示例,包含 UITextField、电子邮件验证和视觉反馈。表单包含两个字段:emailField(emailAddress 键盘,无自动更正)和 passwordField (secureTextEntry)。验证在 shouldChangeCharactersInRange 中进行,并在按下 Login 按钮时额外进行。视觉反馈:错误时红色边框 (layer.borderColor),验证成功时绿色边框。在 textFieldDidBeginEditing 开始编辑时重置边框。
电子邮件验证 通过格式为 "SELF MATCHES %@" 的 NSPredicate 和用于基本格式检查的正则表达式进行。电子邮件的实际存在检查应在服务器上执行。对于高级验证,请使用 SwiftValidators 库或 Combine publishers。示例:NSPredicate(format: "SELF MATCHES [c] %@", emailRegex).evaluate(with: email)。字段边框通过 animation block 更新以实现平滑过渡。
func validateEmail(textField: UITextField) {
guard let text = textField.text, !text.isEmpty else {
textField.layer.borderColor = UIColor.clear.cgColor
return
}
let emailRegex = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.\\p{L}{2,}"
let predicate = NSPredicate(format: "SELF MATCHES [c] %@", emailRegex)
let isValid = predicate.evaluate(with: text)
UIView.animate(withDuration: 0.2) {
textField.layer.borderColor = isValid
? UIColor.systemGreen.cgColor
: UIColor.systemRed.cgColor
textField.layer.borderWidth = 1.0
textField.layer.cornerRadius = 6.0
}
}
常见问题
使用委托方法 shouldChangeCharactersInRange。将新文本长度计算为 existingText.count + newText.count - range.length,如果超过限制则返回 false。替代方法:通过 addTarget 订阅 editingChanged 事件,并通过 textField.text = String(text.prefix(maxLength)) 截断文本。
检查:isUserInteractionEnabled = true(默认),委托在 shouldBeginEditing 中不返回 false。如果字段在 UIScrollView 内 — 禁用 delaysContentTouches。如果字段在模态控制器中 — 检查它是否阻止触摸。对于 SwiftUI UIViewRepresentable,检查字段是否通过 DispatchQueue.main.async 正确成为 firstResponder。
将 UITapGestureRecognizer 添加到 self.view 或 scrollView,并添加调用 view.endEditing(true) 的 target-action。替代方法:textField.resignFirstResponder() 用于隐藏特定字段的键盘。在 UIViewController 中配置 touchesBegan,或使用 IQKeyboardManager 库自动管理键盘。不要忘记禁用 cancelsTouchesInView 以确保按钮正常工作。
文本颜色:textField.textColor = UIColor.label。字体:textField.font = UIFont.systemFont(ofSize: 16, weight: .regular)。Placeholder 颜色:textField.attributedPlaceholder = NSAttributedString(string: "Email", attributes: [.foregroundColor: UIColor.secondaryLabel])。
三种方法:isEnabled = false(更改外观),isUserInteractionEnabled = false(保持视觉样式),或在委托的 textFieldShouldBeginEditing 中返回 false。第三种方法更可取 — 它阻止输入而不改变视觉样式。要以编程方式在只读模式下设置文本,请使用委托。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。