1
votes

I have UITextField whose owner is the delegate for the textfield. I have declared the UITextField as below:

 self.thresholdValueTextField.delegate = self;

NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[numberFormatter setMaximumFractionDigits:2];
[numberFormatter setMinimumFractionDigits:2];

self.thresholdValueTextField.text = [numberFormatter stringFromNumber:[NSNumber numberWithInt:0]];

When the user keeps pressing on the back button even the string is $0.00, my app crashes due to the following error:

*** Terminating app due to uncaught exception 'NSDecimalNumberOverflowException', reason: 'NSDecimalNumber overflow exception'    

Given below is the code that handles textField: shouldChangeCharactersInRange: delegate method:

- (BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString*)string
{
  NSInteger MAX_DIGITS = 10; // $999,999,999.99

  NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
  [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
  [numberFormatter setMaximumFractionDigits:2];
  [numberFormatter setMinimumFractionDigits:2];

  NSString *stringMaybeChanged = [NSString stringWithString:string];
  if (stringMaybeChanged.length > 1)
  {
     NSMutableString *stringPasted = [NSMutableString stringWithString:stringMaybeChanged];

     [stringPasted replaceOccurrencesOfString:numberFormatter.currencySymbol
                                  withString:@""
                                     options:NSLiteralSearch
                                       range:NSMakeRange(0, [stringPasted length])];

     [stringPasted replaceOccurrencesOfString:numberFormatter.groupingSeparator
                                  withString:@""
                                     options:NSLiteralSearch
                                       range:NSMakeRange(0, [stringPasted length])];

     NSDecimalNumber *numberPasted = [NSDecimalNumber decimalNumberWithString:stringPasted];
     stringMaybeChanged = [numberFormatter stringFromNumber:numberPasted];
  }

   UITextRange *selectedRange = [textField selectedTextRange];
   UITextPosition *start = textField.beginningOfDocument;
   NSInteger cursorOffset = [textField offsetFromPosition:start toPosition:selectedRange.start];
   NSMutableString *textFieldTextStr = [NSMutableString stringWithString:textField.text];
   NSUInteger textFieldTextStrLength = textFieldTextStr.length;

   [textFieldTextStr replaceCharactersInRange:range withString:stringMaybeChanged];

   [textFieldTextStr replaceOccurrencesOfString:numberFormatter.currencySymbol
                                  withString:@""
                                     options:NSLiteralSearch
                                       range:NSMakeRange(0, [textFieldTextStr length])];

   [textFieldTextStr replaceOccurrencesOfString:numberFormatter.groupingSeparator
                                  withString:@""
                                     options:NSLiteralSearch
                                       range:NSMakeRange(0, [textFieldTextStr length])];

   [textFieldTextStr replaceOccurrencesOfString:numberFormatter.decimalSeparator
                                  withString:@""
                                     options:NSLiteralSearch
                                       range:NSMakeRange(0, [textFieldTextStr length])];

   if (textFieldTextStr.length <= MAX_DIGITS)
   {
    NSDecimalNumber *textFieldTextNum = [NSDecimalNumber decimalNumberWithString:textFieldTextStr];
    NSDecimalNumber *divideByNum = [[[NSDecimalNumber alloc] initWithInt:10] decimalNumberByRaisingToPower:numberFormatter.maximumFractionDigits];
    NSDecimalNumber *textFieldTextNewNum = [textFieldTextNum decimalNumberByDividingBy:divideByNum];
    NSString *textFieldTextNewStr = [numberFormatter stringFromNumber:textFieldTextNewNum];

    textField.text = textFieldTextNewStr;

    if (cursorOffset != textFieldTextStrLength)
    {
        NSInteger lengthDelta = textFieldTextNewStr.length - textFieldTextStrLength;
        NSInteger newCursorOffset = MAX(0, MIN(textFieldTextNewStr.length, cursorOffset + lengthDelta));
        UITextPosition* newPosition = [textField positionFromPosition:textField.beginningOfDocument offset:newCursorOffset];
        UITextRange* newRange = [textField textRangeFromPosition:newPosition toPosition:newPosition];
        [textField setSelectedTextRange:newRange];
     }
   }

  return NO;
}

May I know what's causing this error?

1
Step through your code with the debugger. See which statement is raising the exception. Then see what the string values are that you are trying to use.user3821934

1 Answers

3
votes

The issue was with the DecimalNumberByDividingBy for [NSDecimalNumber Zero] and NaN occurence.

Updating the code for DecimalNumberByDivindingBy solved it

 NSDecimalNumber *textFieldTextNewNum;
 if ([textFieldTextNum compare:[NSDecimalNumber zero]] == NSOrderedSame || [[NSDecimalNumber notANumber] isEqualToNumber:textFieldTextNum]) {
        textFieldTextNewNum = [NSDecimalNumber zero];
 }else{
        textFieldTextNewNum = [textFieldTextNum decimalNumberByDividingBy:divideByNum];
 }