当前位置:  开发笔记 > 编程语言 > 正文

如何限制NSTextField文本长度并始终保持大写?

如何解决《如何限制NSTextField文本长度并始终保持大写?》经验,为你挑选了4个好方法。

需要一个NSTextField,其文本限制最多为4个字符,并且始终以大写形式显示,但无法找到实现该目标的好方法.我试图通过与验证方法的绑定来实现它,但只有在控件失去第一个响应者时才会调用验证,这并不好.

暂时我通过在文本字段上观察通知NSControlTextDidChangeNotification并让它调用方法来使其工作:

- (void)textDidChange:(NSNotification*)notification {
  NSTextField* textField = [notification object];
  NSString* value = [textField stringValue];
  if ([value length] > 4) {
    [textField setStringValue:[[value uppercaseString] substringWithRange:NSMakeRange(0, 4)]];
  } else {
    [textField setStringValue:[value uppercaseString]];
  }
}

但这肯定不是最好的方法.还有更好的建议吗?



1> Carlos Barbo..:

我按照Graham Lee的建议做了,它工作正常,这是自定义格式化代码:

更新:添加Dave Gallagher报道的修复程序.谢谢!

@interface CustomTextFieldFormatter : NSFormatter {
  int maxLength;
}
- (void)setMaximumLength:(int)len;
- (int)maximumLength;

@end

@implementation CustomTextFieldFormatter

- (id)init {

   if(self = [super init]){

      maxLength = INT_MAX;
   }

  return self;
}

- (void)setMaximumLength:(int)len {
  maxLength = len;
}

- (int)maximumLength {
  return maxLength;
}

- (NSString *)stringForObjectValue:(id)object {
  return (NSString *)object;
}

- (BOOL)getObjectValue:(id *)object forString:(NSString *)string errorDescription:(NSString **)error {
  *object = string;
  return YES;
}

- (BOOL)isPartialStringValid:(NSString **)partialStringPtr
   proposedSelectedRange:(NSRangePointer)proposedSelRangePtr
          originalString:(NSString *)origString
   originalSelectedRange:(NSRange)origSelRange
        errorDescription:(NSString **)error {
    if ([*partialStringPtr length] > maxLength) {
        return NO;
    }

    if (![*partialStringPtr isEqual:[*partialStringPtr uppercaseString]]) {
      *partialStringPtr = [*partialStringPtr uppercaseString];
      return NO;
    }

    return YES;
}

- (NSAttributedString *)attributedStringForObjectValue:(id)anObject withDefaultAttributes:(NSDictionary *)attributes {
  return nil;
}

@end



2> 小智..:

您是否尝试过附加自定义NSFormatter子类?



3> Dave Gallagh..:

在我评论的上述示例中,这很糟糕:

// Don't use:
- (BOOL)isPartialStringValid:(NSString *)partialString
            newEditingString:(NSString **)newString
            errorDescription:(NSString **)error
{
    if ((int)[partialString length] > maxLength)
    {
        *newString = nil;
        return NO;
    }
}

使用此(或类似的东西)代替:

// Good to use:
- (BOOL)isPartialStringValid:(NSString **)partialStringPtr
       proposedSelectedRange:(NSRangePointer)proposedSelRangePtr
              originalString:(NSString *)origString
       originalSelectedRange:(NSRange)origSelRange
            errorDescription:(NSString **)error
{
    int size = [*partialStringPtr length];
    if ( size > maxLength )
    {
        return NO;
    }
    return YES;
}

两者都是NSFormatter方法.第一个有问题.假设您将文本输入限制为10个字符.如果您将字符逐个键入NSTextField,它将正常工作并防止用户超过10个字符.

但是,如果用户要将一个字符串(例如25个字符)粘贴到文本字段中,那么会发生以下情况:

1)用户将粘贴到TextField中

2)TextField将接受字符串

3)TextField将格式化程序应用于25长度字符串中的"last"字符

4)Formatter对25长度字符串中的"last"字符进行填充,忽略其余字符

5)TextField最终将包含25个字符,即使它限制为10个字符.

这是因为,我认为,第一种方法仅适用于键入NSTextField的"最后一个字符".上面显示的第二种方法适用于键入NSTextField的"所有字符".所以它不受"粘贴"攻击的影响.

我刚刚发现这个试图破坏我的应用程序,并且不是NSFormatter的专家,所以如果我错了请纠正我.非常感谢carlosb发布这个例子.它帮了很多!:)


用户甚至不需要粘贴.用户定义的自定义键绑定(有关详细信息,请参阅http://www.hcs.harvard.edu/~jrus/site/cocoa-text.html)可以插入任何字符串,以及基本多语言之外的单个代码点在Cocoa的双字节(UTF-16)意义上,Plane将是多个"字符".

4> Jonathan Mit..:

该实现采用了上面提到的几个建议.值得注意的是,它可以正常连续更新绑定.

此外:

    它正确实现了粘贴.

    它包含一些关于如何在nib中有效使用该类而无需进一步子类化的注释.

代码:

@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


@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] uppercaseString];

        // 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;
}

@end

推荐阅读
U友50081205_653
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有