2014-09-06 38 views
9

Tamam, bu garip. [NSDecimalNumber integerValue] garip davranıyor.{NSDecimalNumber integerValue} garip davranışı

Uygulamamın bazı bölümlerinin neden iOS8'de bozuk olduğunu anlamaya çalışan bir kesme noktasında oturdum ve "timeSeconds" adlı bir değişkene bakıyorum. Bu Xcode Değişkenleri'nde gibi görünür bakın:

_timeSeconds (NSDecimalNumber *) 344.514533996581994496 

Ama ayıklayıcısında bunu sorguladığınızda, bu bkz:

(lldb) p [self.timeSeconds doubleValue] 
(double) $14 = 344.51453399658192 
(lldb) p [self.timeSeconds intValue] 
(int) $15 = 344 
(lldb) p [self.timeSeconds integerValue] 
(NSInteger) $16 = -5 
(lldb) p (NSInteger)[self.timeSeconds intValue] 
(NSInteger) $17 = 344 

"-5" Görüyor? Bir radarı dosyalamadan önce, herhangi biriniz güzel insanlar çoğaltabilir mi, açıklayabilir mi? peşin

NSDecimalNumber *n = [NSDecimalNumber decimalNumberWithString:@"344.514533996581994496"]; 
NSLog(@"%@", n); // 344.514533996581994496 
NSLog(@"%ld", (long)[n intValue]); // 344 
NSLog(@"%ld", (long)[n integerValue]); // -5 
NSLog(@"%ld", (long)[n unsignedIntegerValue]); // 12 

Teşekkür:

İşte SSCCE var!

Matta

+0

Matthew: Burada fazla duyarlık 64 bit gerektiren numaralara alakalı olduğunu gösteren, sorunu gösteren bir birim test mi? IOS 8'deki NSDecimalNumber, canlı uygulamada büyük sorunlara yol açıyor! – SAHM

cevap

12

TamsayıDeğer için sonuç şaşırtıcıdır, ama belgelendiği gibi anladığım kadarıyla:

NSDecimalNumber devralır NSNumber dan. NSNumber alt sınıf notlarında, "... alt sınıfının bildirilen türe karşılık gelen erişimci yöntemini geçersiz kılması gerektiği belirtilmiştir; örneğin, eğer objCType uygulamanız" i "değerini döndürürse, intValue değerini geçersiz kılmanız gerekir. Bu NSNumber için aynı olmalıdır, böylece. "

objCType

iç işaretçi olarak ayarlanır.

NSDecimalintergerValue geçersiz kılmaz. doubleValue'u geçersiz kılar, bu da düzgün çalışmalıdır. buna intValue ya ...

+0

Kesinlikle doğru yolda olduğunuzu düşünüyorum. Bunu biraz daha iyi anlamak isterim ve intValue hakkında bilgi verirseniz, lütfen cevabınızı gönderin. Ama ben devam edip ödül kazanacağım çünkü bence bu doğru yön ve ben sana ödül vermeden lütfun tükenmesini istemiyorum. – SAHM

+0

Bu sorun, büyük olasılıkla bu sorunla ilgili bir NSDecimal sorun daha belirli bir durumda olduğu ilgili bir sorudur. http://stackoverflow.com/questions/26741233/ios-8-number-conversion-formatting-error-cannot-reproduce – SAHM

2

Ne büyük hata geçersiz kılmaz görünüyor: Beni meraklandırıyor

tek şey! Sadece kendim tarafından kandırıldım buldum. Yani, sadece sonuçlandırmak için dogsgods cevap:

yapın DEĞİL:

NSInteger x = [myDecimalNumber integerValue]; 

Bunun yerine, BU yapın:

NSInteger x = (NSInteger)[myDecimalNumber doubleValue]; 
0

Kullanım myDecimalNumber.intValue yerine integerValue

0

Sen kullanım intValue veya unsignedIntValue kullanabilirsiniz sadece iyi, ama değil tamsayıValue veya unsignedIntegerValue.- ne buldun

// 
// NSDecimalNumberBugTests.m 
// 
// Created by Lane Roathe on 6/1/17. 
// For Quicken, Inc. 
// 

#import <XCTest/XCTest.h> 

@interface NSDecimalNumberBugTests : XCTestCase 

@end 

@implementation NSDecimalNumberBugTests 

- (void)setUp { 
    [super setUp]; 
    // Put setup code here. This method is called before the invocation of each test method in the class. 
} 

- (void)tearDown { 
    // Put teardown code here. This method is called after the invocation of each test method in the class. 
    [super tearDown]; 
} 

- (void)testBug { 
    // Use XCTAssert and related functions to verify your tests produce the correct results. 
    NSDecimalNumber* decimalLength; 
    NSUInteger interval; 

    // Start with a number that requires 65+ bits 

    // This FAILS (interval is zero) 
    decimalLength = [NSDecimalNumber decimalNumberWithString:@"1.8446744073709551616"]; 
    interval = decimalLength.unsignedIntegerValue; 
    XCTAssert(interval == 1); 

    // This Works, interval is 1 
    interval = decimalLength.unsignedIntValue; 
    XCTAssert(interval == 1); 

    // Now test with a number that fits in 64 bits 

    // This WORKS (interval is 1) 
    decimalLength = [NSDecimalNumber decimalNumberWithString:@"1.8446744073709551615"]; 
    interval = decimalLength.unsignedIntegerValue; 
    XCTAssert(interval == 1); 
} 

@end