SwiftUI中TextField自动加连字符遇删除异常,求转UIKit对应实现
SwiftUI TextField实现3字符后自动加连字符并修复删除异常
问题分析
你原来的代码在删除字符时会卡在111-状态,原因是只要文本长度等于3就自动添加连字符——哪怕是用户删除连字符后回到3个字符的情况,代码也会立刻重新加上连字符,导致无法正常编辑到3位以下。
解决方案
我们可以通过自定义Binding来模拟UIKit中textField(_:shouldChangeCharactersIn:replacementString:)的逻辑:区分输入和删除操作,仅在用户输入字符时自动添加连字符,删除操作时允许自由编辑,同时保持格式规范和长度限制。
完整代码如下:
import SwiftUI struct ContentView: View { @State private var postalCode = "" private var formattedPostalCode: Binding<String> { Binding( get: { self.postalCode }, set: { newValue in // 先移除所有已存在的连字符,处理原始输入内容 let filteredInput = newValue.replacingOccurrences(of: "-", with: "") // 获取当前已格式化文本的原始长度(去掉连字符) let currentOriginalLength = self.postalCode.replacingOccurrences(of: "-", with: "").count // 判断是输入字符(长度增加)还是删除字符(长度减少/不变) let isAddingCharacter = filteredInput.count > currentOriginalLength var resultText = filteredInput if isAddingCharacter { // 输入操作:在第3个字符后添加连字符 if resultText.count > 3 { resultText.insert("-", at: resultText.index(resultText.startIndex, offsetBy: 3)) } // 限制总长度(含连字符最多8位,即111-1111格式) if resultText.count > 8 { resultText = String(resultText.prefix(8)) } } else { // 删除操作:直接使用过滤后的内容,不自动添加连字符 resultText = filteredInput } self.postalCode = resultText } ) } var body: some View { TextField("PostalCode", text: formattedPostalCode) .padding() .border(Color.gray) } }
逻辑说明
- 过滤连字符:每次处理输入时先移除所有连字符,避免重复添加或格式混乱。
- 区分操作类型:通过对比过滤前后的文本长度,判断用户是在输入还是删除字符。
- 输入时格式化:只有输入字符时,在第3位后自动插入连字符,并限制总长度不超过8位。
- 删除时自由编辑:删除操作时直接保留用户修改后的内容,不会强制添加连字符,解决了无法退回到3位以下的问题。
内容的提问来源于stack exchange,提问作者Taro
相关产品推荐
相关产品推荐

