以下方法从UITextField获取输入并将其格式化以供显示。这段代码多年来一直运行良好,但是使用iOS 8.1在iPhone 6 Plus上报告了一个问题。它每次都发生在用户身上,但我无法重现它。我相信它与iOS 8上的NSNumber / NSDecimalNumber转换和格式有关,可能对于64位应用程序/设备。
用于输入的键盘是数字键盘,因此可输入文本字段的唯一文本是数字0-9和"删除"。
根据用户的说法,这就是正在发生的事情:
我正在尝试输入250美元的预算金额。当我把它拉起来 最初是显示0.00。然后,一旦我输入2,它就会显示出来 220.02然后当我输入5它说2,200.25然后当我输入0时它会出现22,002.50如果我试图删除它出现的任何数字 数量非常多。
根据我测试,下面的代码在iOS 8.1中与模拟器中的每台设备完美配合,包括iPhone 6 Plus。它也适用于iOS 8.1的iPhone 5S设备(64位)。我没有iPhone 6 Plus设备。
我错过了某人看到可能导致此错误的内容吗?
编辑: 这可能是因为decimalNumberWithMantissa参数应该是unsigned long long并且我使用NSInteger?这会导致问题,如果是这样,为什么它会在iPhone 6 Plus上的iOS 8.1之前有效?如果可以的话,我会亲自检查一下......
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;
}
编辑: 似乎这样answer可能在正确的轨道上,只是不确定这将如何翻译。会改变
//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];
到
//scale the price for currency
NSDecimalNumber *priceScaled = [NSDecimalNumber decimalNumberWithMantissa:[priceNumberBeforeScale unsignedLongLongValue] exponent:(0-[[[ObjectsHelper sharedManager] currencyScale] integerValue]) isNegative:NO];
可能解决问题吗?
答案 0 :(得分:1)
似乎iOS 8的自定义键盘可能存在问题。需要进一步调查,但此时至少有一次此问题已通过从设备中删除自定义键盘得到修复。
编辑:是否确认此特定问题是由iOS 8自定义键盘应用程序引起的。该问题已向该应用的发布商报告。