2016-05-31 6 views
1

Мое приложение запоминает MPMediaItems с помощью persistentId, как и каждый. Он сохраняет файл persistentId в файле JSON, который затем считывается и анализируется. NSJSONSerialization создает NSDecimalNumber, чтобы содержать идентификатор, который мое приложение позже использует в MPMediaQuery для получения MPMediaItem.NSDecimalNumber возвращает неправильное значение uint64_t

Я обнаружил, что иногда обнаруживается неправильный MPMediaItem. Когда я еще несколько раз зациклился, я обнаружил, что когда я конвертирую NSDecimalNumber в значение uint64_t, [NSNumber unsignedLongLongValue] возвращает неправильное значение!

NSDecimalNumber* const songId = _songId; 
uint64_t   const songIdValue = songId.unsignedLongLongValue; 

songId is  1457249251113381177 
songIdValue is 1457249251113381120 
-or- 
songId is  0x1439307919d12d39 
songIdValue is 0x1439307919d12d00 

Что, черт возьми? Похоже, что младший байт очищается при преобразовании этого NSDecimalNumber в uint64_t. Является ли это каким-то правильным поведением для NSDecimalNumber, я нашел в нем ошибку?

Я работаю над этим, преобразовывая NSDecimalNumber из NSJSONSerialization в строку и преобразовывая строку в uint64_t с помощью [NSString longLongValue].

Это страшно, потому что кажется, что я сейчас пошел и проверил КАЖДОЕ место. Я храню большие целые числа в файлах JSON и удостоверяюсь, что я их оцениваю в этом способе NSString-y.

+0

Я нашел здесь комментарий, в котором говорится, что NSDecimalNumber преобразуется в double перед преобразованием в uint64_t. Поэтому любые значимые биты за пределами 53 очищаются, как я видел здесь. Невероятно, что Apple разрешает эту позицию! NSJsonSerialization ошибочно выбирает этот класс для целых чисел, а не NSNumber. Я собираюсь переключить мой JSON-анализ на JSONKit, и я бы посоветовал кому-то еще сделать то же самое. –

+0

В своем комментарии Кристофер может ссылаться на [этот ответ на * NSDecimalNumber и большие беззнаковые долго длинные (64-битные) целые числа *] (http://stackoverflow.com/questions/6710469/nsdecimalnumber-and-large-unsigned-long -длинный-64-разрядные целые числа/6713550 # 6713550) – CRD

ответ

0

Если вы хотите сохранить максимум точности, вы можете:

Работа только с NSDecimalNumbers,

Используйте NSString, когда вы передаете значение NSDecimalNumber другой переменной, которая не является NSDecimalNumber. Такие методы, как [NSDecimalNumber longLongValue] или [NSDecimalNumber doubleValue], недостаточно специфичны.

NSDecimalNumber  *songId; 
uint64_t   songIdValue; 
NSString   *intermediateStr; 

songId = [NSDecimalNumber decimalNumberWithString:@"1457249251113381177"]; 
intermediateStr = songId.stringValue; 
songIdValue = intermediateStr.longLongValue; 

Почему использование строк точнее других методов? Я не знаю. Но songIdValue содержит правильное значение без потерь.

 Смежные вопросы

  • Нет связанных вопросов^_^