Skip to content

Instantly share code, notes, and snippets.

@laevandus
Last active August 30, 2020 00:56
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save laevandus/3ca9217a4ad5424733f913faeac93588 to your computer and use it in GitHub Desktop.
Save laevandus/3ca9217a4ad5424733f913faeac93588 to your computer and use it in GitHub Desktop.
struct NumberTextField: View {
init(_ title: String, value: Binding<NSNumber>, formatter: NumberFormatter) {
self.title = title
self.stringTransformer = StringTransformer(value, formatter: formatter)
}
private let title: String
@ObservedObject private var stringTransformer: StringTransformer
var body: some View {
TextField(title, text: $stringTransformer.stringValue)
}
}
fileprivate extension NumberTextField {
final class StringTransformer: ObservableObject {
private var cancellable: AnyCancellable?
init(_ value: Binding<NSNumber>, formatter: NumberFormatter) {
// NSNumber -> String
stringValue = formatter.string(from: value.wrappedValue) ?? ""
// String -> NSNumber
cancellable = $stringValue.dropFirst().receive(on: RunLoop.main)
.sink(receiveValue: { [weak self] (editingString) in
if let number = formatter.number(from: editingString) {
value.wrappedValue = number
}
else if !editingString.isEmpty {
// Force current model value when editing value is invalid (invalid value or out of range).
self?.stringValue = formatter.string(from: value.wrappedValue) ?? ""
}
})
}
@Published var stringValue: String = ""
}
}
@bsiegfreid
Copy link

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment