On Oct 24, 2013, at 9:01 AM, [email protected] wrote:
> 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.
I recall that this can be tricky. Below is a method that I dug up from an old
NSFormatter subclass that handles both min/max lengths, non-stored delimiters
and filtering to acceptable characters, which I recall is also paste-proof. I
can send the whole class files if you care.
- (BOOL)isPartialStringValid:(NSString **)partial
proposedSelectedRange:(NSRange *)proposedRange originalString:(NSString
*)original originalSelectedRange:(NSRange)originalRange
errorDescription:(NSString **)errorDescription
{
// ignore empty
if( ! [*partial length] ) return YES;
// we want a mutable string
NSMutableString *newString = [NSMutableString stringWithString:*partial];
// if single deletion, adjust to ignore delimiters by changing what is
expected to be deleted
if( proposedRange->location == originalRange.location && originalRange.length
== 1 && originalRange.location > 0 )
{
while( ! [allowedCharacters characterIsMember:[original
characterAtIndex:proposedRange->location]] )
{
proposedRange->location--;
}
// re-adjust string & change orig
[newString deleteCharactersInRange:NSMakeRange(
proposedRange->location, originalRange.location - proposedRange->location )];
originalRange.location = proposedRange->location;
}
NSUInteger proposedLocation = proposedRange->location;
// strip down--this will include removing delimiters & updating location
[newString setString:[self filterToAllowed:newString
location:&proposedLocation]];
// are we too long?
if( maxLength > 0 && [newString length] > maxLength )
{
// delete from added
NSUInteger delta = [newString length] - maxLength;
proposedLocation -= delta;
[newString deleteCharactersInRange:NSMakeRange( proposedLocation, delta
)];
NSBeep();
}
// determine the string being added: if deletion or filter actions make orig
before proposed, consider empty added
NSString *addedString = nil;
if( originalRange.location < proposedLocation )
addedString = [newString substringWithRange:NSMakeRange(
originalRange.location, proposedLocation-originalRange.location )];
if( [addedString length] )
{
addedString = [self caseFoldString:addedString precursor:[newString
substringToIndex:originalRange.location]];
[newString replaceCharactersInRange:NSMakeRange(
originalRange.location, proposedLocation-originalRange.location )
withString:addedString];
}
else if( originalRange.location < [newString length] )
{
// if no added--i.e. deletion or all added was filtered out--only check
case folding if not at end
addedString = [self caseFoldString:[newString
substringWithRange:NSMakeRange( originalRange.location, 1 )]
precursor:[newString substringToIndex:originalRange.location]];
[newString replaceCharactersInRange:NSMakeRange(
originalRange.location, 1 ) withString:addedString];
}
// now format & check changed
NSString *finalString = [self formatString:newString
location:&proposedLocation];
BOOL valid = [*partial isEqualToString:finalString];
// update proposed location
proposedRange->location = proposedLocation;
// check completions
if( completions )
{
NSUInteger i, count = [completions count];
for( i=0; i<count; i++ )
{
NSString *proposed = [completions objectAtIndex:i];
if( [proposed rangeOfString:finalString
options:NSCaseInsensitiveSearch].location == 0 && [proposed length] >=
[finalString length] )
{
*proposedRange = NSMakeRange( [finalString length], [proposed
length] - [finalString length] );
finalString = proposed;
break;
}
}
}
// always set
*partial = finalString;
return valid;
}
HTH,
Keary Suska
Esoteritech, Inc.
"Demystifying technology for your home or business"
_______________________________________________
Cocoa-dev mailing list ([email protected])
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 [email protected]