Hi, I'm trying use Formatter for NSTextField to set maximum string length.
I found this https://stackoverflow.com/questions/827014/how-to-limit-nstextfield-text-length-and-keep-it-always-upper-case
But it's for objective-c. I tried this for swift, but it's not working
func controlTextDidChange(_ obj: Notification) {
if let info = obj.userInfo, let text = info["NSFieldEditor"] as? NSText {
let formatter = TextFieldFormatter()
formatter.maxLength = 10
let string = text.string
text.string = formatter.string(for: string.capitalized)!
}
}
Custom formatter class:
class TextFieldFormatter: Formatter {
var maxLength = 0
func setMaximumLength(_ len: Int) {
maxLength = len
}
func maximumLength() -> Int {
return maxLength
}
override init() {
super.init()
maxLength = Int(Int32.max)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func string(for obj: Any?) -> String? {
return obj as? String
}
override func getObjectValue(_ obj: AutoreleasingUnsafeMutablePointer<AnyObject?>?, for string: String, errorDescription error: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool {
obj?.pointee = string as AnyObject
return true
}
override func isPartialStringValid(_ partialStringPtr: AutoreleasingUnsafeMutablePointer<NSString>, proposedSelectedRange proposedSelRangePtr: NSRangePointer?, originalString origString: String, originalSelectedRange origSelRange: NSRange, errorDescription error: AutoreleasingUnsafeMutablePointer<NSString?>?) -> Bool {
let size = partialStringPtr.pointee.length
if size > maxLength {
return false
} else {
return true
}
}
}
I would do this, no need for formatter I think:
func controlTextDidChange(_ obj: Notification) {
guard let textField = obj.object as? NSTextField else { return }
if textField === theTextField { // THIS NOT NEEDED IF ONLY ONE TEXTFIELD
let newLength = textField.stringValue.count
if newLength > 10 {
let newStr = String(textField.stringValue.prefix(10)) // Skip after 10
theTextField.stringValue = newStr
}
}
}
but it's not working
What do you test (type afetr 10 chars ?). What do you get ?
If you want to test with formatter, you should instrument code to understand what's going on.
override func isPartialStringValid(_ partialStringPtr: AutoreleasingUnsafeMutablePointer, proposedSelectedRange proposedSelRangePtr: NSRangePointer?, originalString origString: String, originalSelectedRange origSelRange: NSRange, errorDescription error: AutoreleasingUnsafeMutablePointer<nsstring?>?) -> Bool {
let size = partialStringPtr.pointee.length
print("Size is", size, "Pointee", partialStringPtr.pointee, "maxLength", maxLength)
if size > maxLength {
return false
} else {
return true
}
}