Reputation: 744
I'm trying to format my text in swiftui in a TextField, to add some space like that :
when text changed : 191064221849132 to have 1 91 06 42 218 491 32
I tried with some @state and @Binding, but nothing really work.
Upvotes: 0
Views: 274
Reputation: 16327
You are supposed to use a custom Formatter
or the onCommit
handler. Annoyingly these are not applied as you type, but only when you commit editing
Formatter
example:
final class CapitalizedFormatter: Formatter {
override func string(for obj: Any?) -> String? {
guard let string = obj as? String else {
return ""
}
return string.uppercased()
}
override func getObjectValue(_ obj: AutoreleasingUnsafeMutablePointer<AnyObject?>?, for string: String, errorDescription error: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool {
obj?.pointee = string as NSString
return true
}
}
struct ContentView: View {
@State var capitalizedText: String = ""
var body: some View {
TextField(
"placeholder",
value: $capitalizedText,
formatter: CapitalizedFormatter()
)
}
}
onCommit
example:
struct ContentView: View {
@State var capitalizedText: String = ""
var body: some View {
TextField(
"Placeholder",
text: $capitalizedText,
onCommit: { self.capitalizedText = self.capitalizedText.uppercased() }
)
}
}
If you want continuous text values then use a binding to intercept the new values in the setter, then format them, then emit the value in the getter:
final class Model: ObservableObject {
@Published var capitalizedText = ""
func set(text: String) {
capitalizedText = text.uppercased()
}
}
struct ContentView: View {
@ObservedObject var model: Model
var textBinding: Binding<String>
init() {
let model = Model()
self.textBinding = .init(
get: { model.capitalizedText },
set: { model.set(text: $0) }
)
self.model = model
}
var body: some View {
TextField(
"Placeholder",
text: textBinding
)
}
}
Upvotes: 2