Reputation: 2019
NumberFormatter has a couple methods, number
and string
which seem to imply they are responsible for converting the value to and from each type. However, when trying to override these methods I can't get them to fire.. (the print statements are never seen).
Am I missing something? The only progress I made was with the getObjectValue(_:for:range:)
method in setting the numerical value, but never the string.
import SwiftUI
class NumberProxy : NumberFormatter {
override func string(from number: NSNumber) -> String? {
print("hello from", number)
return "HELLO!"
}
override func number(from string: String) -> NSNumber? {
print("to number...", string)
return NSNumber(value: 123)
}
// override func getObjectValue(_ obj: AutoreleasingUnsafeMutablePointer<AnyObject?>?, for string: String, range rangep: UnsafeMutablePointer<NSRange>?) throws {
// try super.getObjectValue(obj, for: string, range: rangep)
// print(obj)
// obj?.pointee = NSNumber(value: 4.0) // this worked
// }
}
struct Test: View {
@State private var myNumber: Int = 0
var body : some View {
TextField("Current Balance", value: $myNumber, formatter: NumberProxy())
}
}
Upvotes: 0
Views: 449
Reputation: 236498
What you need to override is Formatter
's string(for:)
method:
override func string(for obj: Any?) -> String? {
class NumberProxy: NumberFormatter {
override func string(for obj: Any?) -> String? {
guard let value = (obj as? NSNumber)?.intValue else { return nil }
return .init(value)
}
}
let number = NSNumber(value: 123.456)
let string = NumberProxy().string(from: number) // "123"
edit/update:
To input Double as integers:
override func getObjectValue(_ obj: AutoreleasingUnsafeMutablePointer<AnyObject?>?, for string: String, range rangep: UnsafeMutablePointer<NSRange>?) throws {
try super.getObjectValue(obj, for: string, range: rangep)
obj?.pointee = Int(string.filter(\.isWholeNumber)) as AnyObject?
}
let integer = NumberProxy().number(from: "123.45")!.intValue // 12345
Upvotes: 3