views:

1042

answers:

2

In my iPhone app I employ NSDecimalNumber to store some some currency rate values. I pull the data from the web the first time the app is launched and then again when they become obsolete, and I store them in a NSDictionary; then I use writeToFile:atomically:.

When the app is launched for the first time, my rate conversion method works allright. Yet, when I launch the app a second time, and the rates get loaded with -(NSDictionary*) initWithContentsOfFile: the conversion methos stops working, and I get weird results.

I did some debug with breakpoints in the incriminated method, and I found out that the rates data are seen as NSCFNumber, rather than as NSDecimalNumber. So it appears that initWithContentsOfFile doesn't assign the right class to my objects. For the record, the actual value of these objects, as shown in the description method, corresponds to the expected rate value.

I also checked the plist file generated by writeToFile:atomically:, and saw that the rates are stored as real; I wonder whether this is the right type.

Any idea of whats going on?

Thanks in advance,
Davide

+6  A: 

Property lists don't distinguish between decimal numbers and floating-point numbers. The real element holds a floating-point number. (Indeed, the serialization itself may simply be NSNumber sending floatValue to itself, unaware that the instance is actually of a subclass. That would mean the conversion to floating-point happens when you generate the plist data, not when you read it back in.)

You'll have to store it as a string, I think. Hopefully, that's lossless.

Peter Hosey
I've used the approach of storing NSDecimalNumbers using strings and it seems to do a good job of preserving precision. It appears to be as close to lossless as you can get.
Brad Larson
+5  A: 

Plists only work with certain data types and NSNumber is one of those. If you want the NSDecimalNumber then you have two ways to go about it. The first is to keep using plists and then convert all the NSNumbers to NSDecimalNumbers after load. The second is to switch to using NSKeyedArchiver for storing data. This requires more code but means that if you save an NSDecimalNumber, you'll get an NSDecimalNumber back.

Martin Pilkington
Note that if the property-list serializer is treating the numbers as NSNumbers and asking for their floatValue *when serializing*, then you've already lost precision by that point. It's too late to get that information back.
Peter Hosey
Good point, I guess I'll follow Peter's advice and store the values as NSString.
nutsmuggler