Have I missed something or is access to a decent NSFormatter subclass to handle NSTextField string length limiting troublesome?
There is some form on this: http://stackoverflow.com/questions/827014/how-to-limit-nstextfield-text-length-and-keep-it-always-upper-case/827598#827598 http://www.cocoabuilder.com/archive/cocoa/184885-nsformatter-interfering-with-bindings-continuous-update.html However the solutions provided have issues, some with bindings, and most suggestions don't handle pasted text well. I am currently using the following. Comments, suggested improvements etc welcome. Jonathan @interface BPPlainTextFormatter : NSFormatter { NSInteger _maxLength; } /*! Set the maximum string length. Note that to use this class within a Nib: 1. Add an NSFormatter as a Custom Formatter. 2. In the Identity inspector set the Class to BPPlainTextFormatter 3. In user defined attributes add Key Path: maxlength Type: Number Value: 30 Note that rather than attaching formatter instances to individual cells they can be positioned in the nib Objects section and referenced by numerous controls. A name, such as Plain Text Formatter 100, can be used to identify the formatters max length. */ @property NSInteger maxLength; @end #define _TRACE #import "BPPlainTextFormatter.h" @implementation BPPlainTextFormatter @synthesize maxLength = _maxLength; - (id)init { if(self = [super init]){ self.maxLength = INT_MAX; } return self; } - (id)initWithCoder:(NSCoder *)aDecoder { // support Nib based initialisation self = [super initWithCoder:aDecoder]; if (self) { self.maxLength = INT_MAX; } return self; } #pragma mark - #pragma mark Textual Representation of Cell Content - (NSString *)stringForObjectValue:(id)object { NSString *stringValue = nil; if ([object isKindOfClass:[NSString class]]) { // A new NSString is perhaps not required here // but generically a new object would be generated stringValue = [NSString stringWithString:object]; } return stringValue; } #pragma mark - #pragma mark Object Equivalent to Textual Representation - (BOOL)getObjectValue:(id *)object forString:(NSString *)string errorDescription:(NSString **)error { BOOL valid = YES; // Be sure to generate a new object here or binding woe ensues // when continuously updating bindings are enabled. *object = [NSString stringWithString:string]; return valid; } #pragma mark - #pragma mark Dynamic Cell Editing - (BOOL)isPartialStringValid:(NSString **)partialStringPtr proposedSelectedRange:(NSRangePointer)proposedSelRangePtr originalString:(NSString *)origString originalSelectedRange:(NSRange)origSelRange errorDescription:(NSString **)error { BOOL valid = YES; NSString *proposedString = *partialStringPtr; if ([proposedString length] > self.maxLength) { // The original string has been modified by one or more characters (via pasting). // Either way compute how much of the proposed string can be accommodated. NSInteger origLength = origString.length; NSInteger insertLength = self.maxLength - origLength; // If a range is selected then characters in that range will be removed // so adjust the insert length accordingly insertLength += origSelRange.length; // Get the string components NSString *prefix = [origString substringToIndex:origSelRange.location]; NSString *suffix = [origString substringFromIndex:origSelRange.location + origSelRange.length]; NSString *insert = [proposedString substringWithRange:NSMakeRange(origSelRange.location, insertLength)]; #ifdef _TRACE NSLog(@"Original string: %@", origString); NSLog(@"Original selection location: %u length %u", origSelRange.location, origSelRange.length); NSLog(@"Proposed string: %@", proposedString); NSLog(@"Proposed selection location: %u length %u", proposedSelRangePtr->location, proposedSelRangePtr->length); NSLog(@"Prefix: %@", prefix); NSLog(@"Suffix: %@", suffix); NSLog(@"Insert: %@", insert); #endif // Assemble the final string *partialStringPtr = [NSString stringWithFormat:@"%@%@%@", prefix, insert, suffix]; // Fix-up the proposed selection range proposedSelRangePtr->location = origSelRange.location + insertLength; proposedSelRangePtr->length = 0; #ifdef _TRACE NSLog(@"Final string: %@", *partialStringPtr); NSLog(@"Final selection location: %u length %u", proposedSelRangePtr->location, proposedSelRangePtr->length); #endif valid = NO; } return valid; } _______________________________________________ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com