Борьба с валютой в какао - PullRequest
       29

Борьба с валютой в какао

6 голосов
/ 27 февраля 2009

Я пытаюсь сделать что-то, что, на мой взгляд, будет довольно простым: пусть пользователь вводит сумму в долларах, сохраняет эту сумму в NSNumber (NSDecimalNumber?), А затем через некоторое время снова отображает эту сумму в формате валюты ,

Моя проблема не столько в setNumberStyle: NSNumberFormatterCurrencyStyle и отображении чисел с плавающей точкой. Проблема скорее в том, как указанный numberFormatter работает с этим UITextField. Я могу найти несколько примеров. Эта тема от ноября и эта дают мне некоторые идеи, но оставляют мне больше вопросов.

Я использую клавиатуру UIKeyboardTypeNumberPad и понимаю, что мне, вероятно, следует отображать $ 0,00 (или любой другой формат местной валюты) в поле при отображении, тогда как пользователь вводит цифры, чтобы сдвинуть десятичное место вдоль:

  • Начните с отображения $ 0.00
  • Нажмите кнопку 2: дисплей $ 0,02
  • Нажмите 5 клавиш: дисплей $ 0,25
  • Нажмите 4 клавиши: дисплей $ 2,54
  • Нажмите кнопку 3: дисплей $ 25,43

Тогда [numberFormatter numberFromString: textField.text] должно дать мне значение, которое я могу сохранить в моей переменной NSNumber.

К сожалению, я все еще борюсь: действительно ли это лучший / самый простой способ? Если так, то, возможно, кто-то может помочь мне с реализацией? Я чувствую, что UITextField может понадобиться делегат, отвечающий на каждое нажатие клавиши, но не уверен, что, где и как это реализовать ?! Любой пример кода? Я очень ценю это! Я искал все выше и ниже ...

Edit1: Итак, я смотрю на stringForObjectValue: NSFormatter и ближайшую вещь, которую я могу найти из того, что рекомендует benzado: UITextViewTextDidChangeNotification . Мне очень трудно найти пример кода на любом из них ... так что дайте мне знать, если вы знаете, где искать?

Ответы [ 7 ]

10 голосов
/ 29 мая 2010

Мое решение:

<code>
- (BOOL)textField:(UITextField *)textField
    shouldChangeCharactersInRange:(NSRange)range 
    replacementString:(NSString *)string
{
  // Clear all characters that are not numbers
  // (like currency symbols or dividers)
  NSString *cleanCentString = [[textField.text
    componentsSeparatedByCharactersInSet:
    [[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
      componentsJoinedByString:@""];
  // Parse final integer value
  NSInteger centAmount = cleanCentString.integerValue;
  // Check the user input
  if (string.length > 0)
  {
    // Digit added
    centAmount = centAmount * 10 + string.integerValue;
  }
  else
  {
    // Digit deleted
    centAmount = centAmount / 10;
  }
  // Update call amount value
  [_amount release];
  _amount = [[NSNumber alloc] initWithFloat:(float)centAmount / 100.0f];
  // Write amount with currency symbols to the textfield
  NSNumberFormatter *_currencyFormatter = [[NSNumberFormatter alloc] init];
  [_currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
  [_currencyFormatter setCurrencyCode:@"USD"];
  [_currencyFormatter setNegativeFormat:@"-¤#,##0.00"];
  textField.text = [_currencyFormatter stringFromNumber:_amount];
  [_currencyFormatter release]
  // Since we already wrote our changes to the textfield
  // we don't want to change the textfield again
  return NO;
}
3 голосов
/ 27 февраля 2009

Вот примерный план атаки, который я бы использовал, если бы мне пришлось написать это сейчас. Хитрость заключается в том, чтобы ввести скрытый UITextField и обновить UILabel с форматированным значением по мере того, как пользователь печатает.

  1. Создайте UITextField, сделайте его скрытым, назначьте его делегатом и сделайте его первым респондентом, который вызовет клавиатуру.
  2. В вашем делегате ответьте на сообщение textDidChange: (слишком лениво, чтобы найти точное имя), взяв новое значение текстового поля и преобразовав его в число. Убедитесь, что пустая строка конвертируется в ноль.
  3. Пропустите номер через ваш форматтер и обновите UILabel с этим отформатированным значением валюты.

При каждом нажатии клавиши метка будет обновляться, поэтому пользователь будет чувствовать, что он редактирует форматированное значение, когда он действительно редактирует скрытое текстовое поле. Как подлый!

1 голос
/ 08 сентября 2011

Поскольку я ленивый и не могу переформатировать свой ввод, чтобы «выручить меня» на лету, я говорю:

Просто дайте им ввести десятичное число. Когда они покидают поле, переформатируйте его.

1 голос
/ 21 апреля 2010

Ну, я думаю, что это лучше:

- (void)viewWillDisappear:(BOOL)animated{ [[NSNotificationCenter defaultCenter] removeObserver:self  name:UITextFieldTextDidChangeNotification object:nil]; }

-(void)viewDidAppear:(BOOL)animated{
 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChanged:) name:UITextFieldTextDidChangeNotification object:nil];
}

-(void)textDidChanged:(NSNotification *)notification{
 [[NSNotificationCenter defaultCenter] removeObserver:self  name:UITextFieldTextDidChangeNotification object:nil];
 UITextField * textField= [notification object];
 NSString * sinPesos= [textField.text stringByReplacingOccurrencesOfString:@"$" withString:@""];
 NSString * sinPuntos= [sinPesos stringByReplacingOccurrencesOfString:@"." withString:@""];

 float monto = [sinPuntos floatValue]; 

 monto= monto/100;

 NSString * cardText= [[self montoFormatter] stringFromNumber:[NSNumber numberWithDouble:monto]]; 

 textField.text = ([cardText isEqualToString: @"0"] ? @"":cardText);
 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChanged:) name:UITextFieldTextDidChangeNotification object:nil];
} 

-(NSNumberFormatter *)montoFormatter{
 NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init];
 [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
 [numberFormatter setMaximumFractionDigits:2];
 return [numberFormatter autorelease];
}

Попробуйте: :)

0 голосов
/ 31 октября 2013

Я написал для этого подкласс UITextField с открытым исходным кодом, доступный здесь:

https://github.com/TomSwift/TSCurrencyTextField

Подход, который я выбрал, похож на то, что Ларс Шнайдер предлагает в своем популярном ответе. Но моя версия полностью инкапсулирована в повторно используемый компонент, который вы используете где угодно, например, UITextField. Если вы решите реализовать какие-либо методы UITextFieldDelegate, вы можете, но это не обязательно.

0 голосов
/ 18 декабря 2009

Вот мое решение!

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
    float valorUnit = [textField.text floatValue];

    if( string.length > 0)
    {
        float incremento = [string floatValue];

        valorUnit = valorUnit * 10.f + (incremento/100.f);
        NSString* strVal = [NSString stringWithFormat:@"%f", valorUnit];

        if (valorUnit > 0.f && valorUnit < 10.f) {
            textField.text  = [strVal substringToIndex:3];
        }
        else if (valorUnit < 100.f && valorUnit >= 10.f)
        {
            textField.text  = [strVal substringToIndex:4];
        }
        else if (valorUnit >=100.f && valorUnit <1000.f)
        {
            textField.text  = [strVal substringToIndex:5];
        }
        else {
            return NO;
        }

    }
    else {
        valorUnit = (valorUnit/10.f);
        NSString* strVal = [NSString stringWithFormat:@"%f", valorUnit];
        if (valorUnit > 0.f && valorUnit < 10.f) {
            textField.text  = [strVal substringToIndex:5];
        }
        else if (valorUnit < 100.f && valorUnit >= 10.f)
        {
            textField.text  = [strVal substringToIndex:6];
        }
        else if (valorUnit >=100.f && valorUnit <1000.f)
        {
            textField.text  = [strVal substringToIndex:7];
        }
        else {
            return NO;
        }
    }

return YES;

}

0 голосов
/ 19 августа 2009

Ну, это немного поздно, но я решил, что все равно попробую. Вероятно, это скорее обходной путь и может быть грязный код, но это сработало для меня. Я подключил метку и скрытое текстовое поле в IB и написал этот код, используя делегат UITextFieldDelegate.

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    if (textField == fineHiddenTextField) {
        NSString *fineText = [textField.text stringByReplacingCharactersInRange:range withString:string];
        if ([fineText length] == 0) {
            NSString *emptyFine = @"0.00";
            float fineValue = [emptyFine floatValue];
            fineEntryLabel.text = [NSString stringWithFormat:@"%.2f", fineValue];
        } else if ([fineText length] == 1) {
            NSString *firstDec = [NSString stringWithFormat:@"0.0%@", fineText];
            float fineValue = [firstDec floatValue];
            fineEntryLabel.text = [NSString stringWithFormat:@"%.2f", fineValue];
        } else if ([fineText length] == 2) {
            NSString *secondDec = [NSString stringWithFormat:@"0.%@", fineText];
            float fineValue = [secondDec floatValue];
            fineEntryLabel.text = [NSString stringWithFormat:@"%.2f", fineValue];
        } else {
            int decimalPlace = [fineText length] - 2;
            NSString *fineDollarAmt = [fineText substringToIndex:decimalPlace];
            NSString *fineCentsAmt = [fineText substringFromIndex:decimalPlace];
            NSString *finalFineValue = [NSString stringWithFormat:@"%@.%@", fineDollarAmt, fineCentsAmt];
            float fineValue = [finalFineValue floatValue];
            fineEntryLabel.text = [NSString stringWithFormat:@"%.2f", fineValue];
        }


        //fineEntryLabel.text = [NSString stringWithFormat:@"%.2f", fineValue];
        return YES;
    }
}

Не совсем удачный, но он действительно сделал свою работу. Первоначальный оператор if был просто для того, чтобы убедиться, что это происходит только для этого одного конкретного textField (поскольку на одной странице их несколько). Этот код был предназначен для ввода денег (сумма уплаченного штрафа), и я хотел это должно быть просто и легко в использовании. Просто установите метку для выравнивания справа, и она должна.

Я сейчас немного занят кофе, но я отвечу на любые ваши вопросы. :)

...