Phương thức sau đây lấy đầu vào từ UITextField và định dạng nó để hiển thị. Mã này đã hoạt động hoàn hảo trong nhiều năm, nhưng một vấn đề đã được báo cáo trên iPhone 6 Plus sử dụng iOS 8.1. Nó xảy ra mỗi lần cho người dùng nhưng tôi đã không thể tái tạo nó. Tôi tin rằng nó đã làm với NSNumber/NSDecimalNumber chuyển đổi và định dạng trên iOS 8, có lẽ cho một ứng dụng 64-bit/thiết bị.Lỗi chuyển đổi/định dạng số iOS 8? (không thể sao chép)
Bàn phím được sử dụng để nhập là một phím số, do đó, văn bản duy nhất có thể được nhập vào trường văn bản là các số 0-9 và "xóa".
Theo người sử dụng, đây là những gì đang xảy ra:
Tôi cố gắng để nhập một lượng ngân sách $ 250. Khi tôi kéo nó lên ban đầu là hiển thị 0,00. Sau đó, ngay sau khi tôi nhập 2, sau đó hiển thị 220,02 sau đó khi tôi nhập 5 nó nói 2,200,25 sau đó khi tôi nhập 0 nó đi lên với 22,002,50 nếu tôi cố gắng xóa bất kỳ số nào nó lên với một số lượng thực sự lớn.
Mã bên dưới hoạt động hoàn hảo với iOS 8.1, theo như tôi đã thử nghiệm, trên mọi thiết bị trong trình mô phỏng, bao gồm cả iPhone 6 Plus. Nó cũng hoạt động trên thiết bị iPhone 5S (64 bit) với iOS 8.1. Tôi không có thiết bị iPhone 6 Plus.
Tôi có thiếu thứ gì đó mà ai đó thấy có thể gây ra lỗi này không?
EDIT: Điều này có thể là do tham số decimalNumberWithMantissa không được ký dài và tôi đang sử dụng NSInteger? Điều này có gây ra vấn đề không, và nếu vậy, tại sao nó lại hoạt động cho đến iOS 8.1 trên iPhone 6 Plus? Tôi sẽ kiểm tra này bản thân mình nếu tôi có thể ...
Các entryField UITextField được khởi tạo như sau:
entryField.text = [NSString stringWithFormat:@"%@", [[[ObjectsHelper sharedManager] currencyFullFormatter] stringFromNumber:[NSDecimalNumber zero]]];
và đây là phần còn lại của các mã có liên quan:
#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;
}
}
Từ DateHelper. m:
+ (NSNumberFormatter *)decimalFormatter {
__ENTERING_METHOD__
NSNumberFormatter *decimalFormatter = [[NSNumberFormatter alloc] init];
[decimalFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
[decimalFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
return decimalFormatter;
}
Từ 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;
}
CHỈNH SỬA: Có vẻ như điều này answer có thể đi đúng hướng, chỉ cần không biết chính xác cách dịch đó tại đây. Sẽ thay đổi
//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];
có khả năng giải quyết vấn đề?
Không biết điều đó có hữu ích hay không, nhưng thay vì "trường hợp thêm/xóa" bạn có thể làm '[mstring replaceCharactersInRange: range withString: string]'. Lưu ý rằng người dùng có thể chọn một phần của trường văn bản và thay thế bằng cách sao chép/dán. –
Cảm ơn bạn. Bạn có tin rằng điều đó sẽ gây ra vấn đề này? Tôi chắc chắn nếu tôi có thể tái sản xuất các lỗi tôi có thể (cuối cùng) sửa chữa nó, nhưng tiếc là tôi là một nhà phát triển độc lập và không có khả năng mua iPhone 6 Plus. Bất kỳ suy nghĩ nào về lý do tại sao một lỗi như thế này sẽ hiển thị mọi lúc trên thiết bị (ít nhất một thiết bị) nhưng không bao giờ trong trình mô phỏng cho thiết bị đó? – SAHM
Ngoài ra, textField không thể chọn, nếu điều đó giúp bất kỳ thứ gì (có thể là không). Cách duy nhất mà người dùng có thể thay đổi nội dung là thông qua bàn phím với các phím 0-9 và xóa. – SAHM