0

I have an NSTextField with an NSNumberFormatter to limit entry to numbers, but it will not allow me to type a hyphen to enter a negative number (even after setting "minimum" to "-1,000").

I can copy/paste a "-1" into the field and programmatically set its value, but users can't enter hyphens.

Is there a way to allow this?

Thanks.

PS, here's the custom formatter I tried (without success) as per Nishant's suggestion below:

import Cocoa

class CustomNumberFormatter: NSNumberFormatter {

    override func isPartialStringValid(partialStringPtr: AutoreleasingUnsafeMutablePointer<NSString?>,
        proposedSelectedRange proposedSelRangePtr: NSRangePointer, originalString origString: String,
        originalSelectedRange origSelRange: NSRange, errorDescription error: AutoreleasingUnsafeMutablePointer<NSString?>) -> Bool {

            return true
    }

}
Marc Fearby
  • 1,305
  • 1
  • 13
  • 28
  • If I had relevant code to post I'd probably have the answer. There's no point posting the XML markup for the NSTextField and its NSNumberFormatter: it's all configured via XCode's interface builder. – Marc Fearby Sep 16 '15 at 06:16
  • You could post a screen shot of interface builder. – matt Sep 16 '15 at 06:44
  • First, describe exactly how you added the number formatter. Second describe (or show) *all* of the number formatter attribute settings. Finally, what you do mean by "it will not let me type a hyphen"? What exactly happens when you try? A beep? An alert dialog? Nothing? By the way, I assume when you say "hyphen" you mean the standard hyphen-minus key on the keyboard. In Unicode, "hyphen" means something different. – Ken Thomases Sep 16 '15 at 06:55
  • Here's what I did: drag a "Text Field with Number Formatter" from the Object Library, dropped it onto a view, expanded Text Field > Text Field Cell > Number Formatter in the Document Outline for MainMenu.xib, set the Minimum value to "-1,000" in the Attributes Inspector. I realise there's a difference between what word processors turn the hyphen into and the key with the underscore above it: I'm talking about the hyphen/dash to mean a minus sign. It will not let me type that character. – Marc Fearby Sep 16 '15 at 09:08
  • What you describe works just fine for me. – Ken Thomases Sep 17 '15 at 02:11
  • I had this problem and found I had not initialized the minimum value to a negative number. – fractor Nov 15 '19 at 11:24
  • You dont use a number formatter. you would use phone number formatter or need to implement a custom formatter for hyphens. numbers do not contain hyphens.. – CDM social medias in bio Dec 15 '22 at 15:54

2 Answers2

1

I know this question is old, but I was (I think) able to use Nishant's answer as inspiration to fix this for real. My solution is below. I overrode three methods. The reason for those three overrides is as follows:

  1. Make it so that a lone minus sign would be treated as a value of 0.

  2. Make it so that if the user string currently contains a lone minus sign, return that minus sign as the string value instead of 0.

  3. Make it so that a lone minus sign is accepted as an input string. (Nishant's original proposed solution.)

NumberFormatterFix.h:

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface NumberFormatterFix : NSNumberFormatter
{
    BOOL minusSign;
}

- (BOOL)getObjectValue:(out id _Nullable * _Nullable)obj forString:(NSString *)string errorDescription:(out NSString * _Nullable * _Nullable)error;
- (nullable NSString *)stringForObjectValue:(nullable id)obj;
- (BOOL)isPartialStringValid:(NSString * _Nonnull * _Nonnull)partialStringPtr proposedSelectedRange:(nullable NSRangePointer)proposedSelRangePtr originalString:(NSString *)origString originalSelectedRange:(NSRange)origSelRange errorDescription:(NSString * _Nullable * _Nullable)error;

@end


NS_ASSUME_NONNULL_END

NumberFormatterFix.m:

#import "NumberFormatterFix.h"

@implementation NumberFormatterFix

- (BOOL)getObjectValue:(out id _Nullable * _Nullable)obj forString:(NSString *)string errorDescription:(out NSString * _Nullable * _Nullable)error
{
    if ([string isEqualToString:@"-"])
    {
        minusSign = YES;
        *obj = [NSNumber numberWithDouble:0.0];
        return YES;
    }
    minusSign = NO;
    return [super getObjectValue:obj forString:string errorDescription:error];
}

- (nullable NSString *)stringForObjectValue:(nullable id)obj
{
    if (minusSign)
    {
        return @"-";
    }
    return [super stringForObjectValue:obj];
}

- (BOOL)isPartialStringValid:(NSString * _Nonnull * _Nonnull)partialStringPtr proposedSelectedRange:(nullable NSRangePointer)proposedSelRangePtr originalString:(NSString *)origString originalSelectedRange:(NSRange)origSelRange errorDescription:(NSString * _Nullable * _Nullable)error
{
    if ([*partialStringPtr isEqualToString:@"-"])
    {
        return YES;
    }
    return [super isPartialStringValid:partialStringPtr proposedSelectedRange:proposedSelRangePtr originalString:origString originalSelectedRange:origSelRange errorDescription:error];
}

@end
tcobbs
  • 309
  • 2
  • 5
  • As an aside, this is probably only necessary if you call floatValue on the text field inside a controlTextDidChange: handler. If you don't do that, the standard NSNumberFormatter should work. – tcobbs May 16 '21 at 00:56
-1

Subclass NSNumberFormatter and implement this method:

- (BOOL)isPartialStringValid:(NSString **)partialStringPtr
       proposedSelectedRange:(NSRangePointer)proposedSelRangePtr
              originalString:(NSString *)origString
       originalSelectedRange:(NSRange)origSelRange
            errorDescription:(NSString **)error

return YES in case your input is a valid number/character as desired by you.

Nishant
  • 12,529
  • 9
  • 59
  • 94
  • Thanks for the suggestion. I created a subclass and set it as the custom class of the relevant Number Formatter in the Identity Inspector. I'm just returning "true" at all times (Swift), and it still won't let me enter a minus sign. – Marc Fearby Sep 16 '15 at 23:42