嗨,我在下面得到了代码,并尝试动态格式化文本输入,但是当一切看起来都不错时,我会尝试编辑光标跳到看起来很奇怪的末尾,我的问题是我们可以防止这种行为。
下面的 gif 演示了该问题。
import SwiftUI
struct ContentView: View {
@State private var text = ""
@State private var error: String?
var body: some View {
VStack {
let config = _TextFieldConfig(titleKey: "",
promptText: "Enter text here",
value: $text,
error: $error,
format: ._parseableFormatStyle)
_TextField(config: config)
}
.padding()
}
}
struct _TextFieldConfig<Format: ParseableFormatStyle> where Format.FormatOutput == String, Format.FormatInput == String, Format.Strategy == _ParseStrategy {
var titleKey: String
var promptText: String
var format: Format
@Binding var value: String
@Binding var error: String?
init(titleKey: String = "",
promptText: String = "",
value: Binding<String>,
error: Binding<String?>,
format: Format) {
self.titleKey = titleKey
self.promptText = promptText
_error = error
_value = value
self.format = format
}
}
struct _TextField: View {
var config: _TextFieldConfig<_ParseableFormatStyle>
init(config: _TextFieldConfig<_ParseableFormatStyle>) {
self.config = config
}
var body: some View {
VStack {
TextField(config.titleKey,
text: config.$value,
prompt: Text(config.promptText))
}
.onChange(of: config.value, initial: false) { oldValue, newValue in
config.value = oldValue.formatted(config.format)
}
}
}
struct _ParseStrategy: ParseStrategy {
func parse(_ value: String) throws -> String {
value
}
}
struct _ParseableFormatStyle: ParseableFormatStyle {
var parseStrategy: _ParseStrategy { .init() }
func format(_ value: String) -> String {
value
.lazy
.filter { $0 != " " }
.chunks(ofCount: 2)
.map { String($0) }
.joined(separator: " ")
}
}
extension ParseableFormatStyle where Self == _ParseableFormatStyle {
static var _parseableFormatStyle: _ParseableFormatStyle { .init() }
}
extension Array {
func chunks(ofCount chunkCount: Int) -> [[Element]] {
var result: [[Element]] = []
for index in stride(from: 0, to: count, by: chunkCount) {
let lastIdx = Swift.min(count, index + chunkCount)
result.append(Array(self[index ..< lastIdx]))
}
return result
}
}
不幸的是,我还没有找到任何可以在 SwiftUI 的 TextField 中操作光标的东西,但这也可能不是问题的根源。
我写了类似的东西,但当我想一次删除 2 个字母时,它的行为是错误的。有人有想法吗?
func textField(_ textField: UITextField,
shouldChangeCharactersIn range: NSRange,
replacementString string: String) -> Bool {
let currentText = textField.text ?? ""
let text = (currentText as NSString).replacingCharacters(in: range, with: string)
let count = text.count
if !string.isEmpty {
if count > 13 {
return false
}
if string.range(of: " ") != nil {
return false
}
if count % 3 == 0 {
textField.text?.insert(" ", at: String.Index(utf16Offset: count - 1, in: currentText))
}
return true
}
return true
}