Ошибка преобразования/форматирования номера iOS 8? (не могу воспроизвести)

Следующий метод принимает входные данные из UITextField и форматирует их для отображения. Этот код работал безупречно в течение многих лет, но только что сообщалось о проблеме на iPhone 6 Plus с iOS 8.1. Это происходит каждый раз для пользователя, но я не смог воспроизвести его. Я считаю, что это связано с преобразованиями и форматированием NSNumber/NSDecimalNumber в iOS 8, возможно, для 64-битного приложения/устройства.

Клавиатура, используемая для ввода, представляет собой цифровую клавиатуру, поэтому единственный текст, который можно ввести в текстовое поле, — это цифры 0–9 и «удалить».

По словам пользователя, происходит следующее:

Я пытаюсь ввести сумму бюджета в размере 250 долларов США. Когда я поднимаю его, сначала отображается 0,00. Затем, как только я ввожу 2, он показывает 220,02, затем, когда я ввожу 5, он говорит 2 200,25, затем, когда я ввожу 0, он показывает 22 002,50, если я пытаюсь стереть любые числа, я получаю действительно большое число.

Приведенный ниже код отлично работает с iOS 8.1, насколько я проверял, на всех устройствах в симуляторе, включая iPhone 6 Plus. Он также работает на устройстве iPhone 5S (64-разрядная версия) с iOS 8.1. У меня нет устройства iPhone 6 Plus.

Я пропустил что-то, что, как кто-то видит, может быть причиной этой ошибки?

РЕДАКТИРОВАТЬ: возможно ли это из-за того, что параметр decimalNumberWithMantissa должен быть беззнаковым длинным, и я использую NSInteger? Может ли это вызвать проблему, и если да, то почему это работало до iOS 8.1 на iPhone 6 Plus? Я бы сам проверил это, если бы мог...

EntryField UITextField инициализируется следующим образом:

entryField.text = [NSString stringWithFormat:@"%@", [[[ObjectsHelper sharedManager] currencyFullFormatter] stringFromNumber:[NSDecimalNumber zero]]];

и вот остальная часть соответствующего кода:

#define MAX__NUMBER_LENGTH 10

- (BOOL)textField:(UITextField *)textFieldHere shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {

    __ENTERING_METHOD__
    NSMutableString *mstring = [[NSMutableString alloc] initWithString:[entryField text]];

    if([string length] > 0){
        //add case
        [mstring insertString:string atIndex:range.location];
    }
    else {
        //delete case - the length of replacement string is zero for a delete
        [mstring deleteCharactersInRange:range];
    }

    NSString *clean_string = [[mstring componentsSeparatedByCharactersInSet:
                               [[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
                              componentsJoinedByString:@""];

    //clean up mstring since it's no longer needed


    if ((clean_string.length >= MAX__NUMBER_LENGTH && range.length == 0) || ([clean_string length] == 0 && [string isEqualToString:@"0"]))
    {
        return NO; // return NO to not change text
    }
    else {

        //get the cleaned price in the form of a NSNumber - it has not yet been scaled
        NSNumber *priceNumberBeforeScale = [[DateHelper decimalFormatter] numberFromString:clean_string];
        self.budgetIntNumber = priceNumberBeforeScale;

        //get the cleaned price in the form of an integer - it has not yet been scaled
        NSInteger priceIntBeforeScale = [priceNumberBeforeScale integerValue];

        //scale the price for currency
        NSDecimalNumber *priceScaled = [NSDecimalNumber decimalNumberWithMantissa:priceIntBeforeScale exponent:(0-[[[ObjectsHelper sharedManager] currencyScale] integerValue]) isNegative:NO];

        //now format the price for currency
        //and get the grouping separators added in and put it in the UITextField
        entryField.text = [[[ObjectsHelper sharedManager] currencyFullFormatter] stringFromNumber:priceScaled];

        //always return no since we are manually changing the text field
        return NO;
    }
}

Из DateHelper.m:

+ (NSNumberFormatter *)decimalFormatter {   

        __ENTERING_METHOD__
        NSNumberFormatter *decimalFormatter = [[NSNumberFormatter alloc] init];
        [decimalFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
        [decimalFormatter setNumberStyle:NSNumberFormatterDecimalStyle];

        return decimalFormatter;
    }

Из ObjectsHelper.m:

- (NSNumberFormatter*)currencyFullFormatter {

    __ENTERING_METHOD__
    if (currencyFullFormatter != nil) {
        return currencyFullFormatter;
    }
    currencyFullFormatter = [[NSNumberFormatter alloc] init];
    [currencyFullFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
    [currencyFullFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];

    return currencyFullFormatter;
}

- (NSNumber*)currencyScale {

    __ENTERING_METHOD__
    if (currencyScale != nil) {
        return currencyScale;
    }
    self.currencyScale = [NSNumber numberWithInteger:[[[ObjectsHelper sharedManager] currencyFullFormatter] maximumFractionDigits]];

    return currencyScale;
}

РЕДАКТИРОВАТЬ: Похоже, что этот ответ может быть на правильном пути, просто не совсем уверен, как это будет здесь переведено. Изменится ли

    //get the cleaned price in the form of an integer - it has not yet been scaled
    NSInteger priceIntBeforeScale = [priceNumberBeforeScale integerValue];

    //scale the price for currency
    NSDecimalNumber *priceScaled = [NSDecimalNumber decimalNumberWithMantissa:priceIntBeforeScale exponent:(0-[[[ObjectsHelper sharedManager] currencyScale] integerValue]) isNegative:NO];

to

    //scale the price for currency
    NSDecimalNumber *priceScaled = [NSDecimalNumber decimalNumberWithMantissa:[priceNumberBeforeScale unsignedLongLongValue] exponent:(0-[[[ObjectsHelper sharedManager] currencyScale] integerValue]) isNegative:NO];

возможно решить проблему?


person SAHM    schedule 04.11.2014    source источник
comment
Не знаю, поможет ли это, но вместо вашего случая добавления/удаления вам, вероятно, следует сделать [mstring replaceCharactersInRange:range withString:string] . Обратите внимание, что пользователь может выбрать часть текстового поля и заменить ее с помощью копирования/вставки.   -  person Martin R    schedule 04.11.2014
comment
Спасибо. Вы верите, что это вызовет эту проблему? Я уверен, что если бы я мог воспроизвести ошибку, я мог бы (в конечном итоге) исправить ее, но, к сожалению, я независимый разработчик и не могу позволить себе купить iPhone 6 Plus. Любые мысли о том, почему такая ошибка будет появляться каждый раз на устройстве (по крайней мере, на одном устройстве), но никогда не в симуляторе для этого устройства?   -  person SAHM    schedule 04.11.2014
comment
Кроме того, textField нельзя выбрать, если это что-то помогает (что, вероятно, не помогает). Единственный способ, которым пользователь может изменить содержимое, — это использовать клавиатуру с клавишами 0-9 и удалить.   -  person SAHM    schedule 04.11.2014
comment
Хорошо, я только что заметил это, когда читал ваш вопрос.   -  person Martin R    schedule 04.11.2014
comment
Есть ли способ улучшить этот вопрос?   -  person SAHM    schedule 07.11.2014


Ответы (1)


Похоже, что может возникнуть проблема с пользовательскими клавиатурами для iOS 8. Необходимо провести дальнейшее расследование, но на данный момент по крайней мере один случай возникновения этой проблемы был устранен путем удаления пользовательской клавиатуры с устройства.

РЕДАКТИРОВАТЬ: Подтверждено ли, что эта конкретная проблема была вызвана пользовательским приложением клавиатуры iOS 8. О проблеме было сообщено издателям приложения.

person SAHM    schedule 11.11.2014
comment
В примечании на боковой панели — должен ли я связаться с Apple по этому поводу? Если сторонние приложения для клавиатуры могут вызвать такую ​​проблему, следует ли об этом уведомить Apple? Я не совсем уверен, как работают такие приложения, но в моем случае казалось, что делегаты UITextfield перезаписываются. - person SAHM; 14.11.2014