views:

51

answers:

2

Hi,

i'm trying to retrieve a value from my preference file which is an integer. The funny thing is that it always returns zero, although it does exist and the names for both integerForKey: and setIntegerForKey: are the same.

Here's how I retrieve the value: [defaults integerForKey:@"BackUpSize"];

And here I set it: [defaults setInteger:[sizeSlider doubleValue]*8589934592 forKey:@"BackUpSize"];

I'm stunned. It should work...or am I missing something here?

Thanks

Edit: defaults is created as such: NSUserDefaults*defaults = [NSUserDefaults standardUserDefaults];

Edit: I've tried creating my own NSUserDefaults method for this issue, but it still returns zero.

-(void)setDouble:(double)dou forKey:(id)key
{
    [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithDouble:dou] forKey:key];
}
-(double)doubleForKey:(id)key
{
    return [[[NSUserDefaults standardUserDefaults] objectForKey:key] doubleValue];
}
A: 

You're passing a double into something that expects an integer. Normally you'd expect some truncation to occur, and to end up with an int, but you can't guarantee that the setInteger:forKey: method is doing that for you.

Why are you multiplying your slider value by that apparently arbitrary number?

Edit:

To explain my answer a little more:

In order to store numbers in the defaults they need to be wrapped in NSNumber objects. setInteger:forKey, et al, are convenience methods that probably just take your integer and create an NSNnumber from it, using numberWithInt:. I can't be 100% sure because I haven't seen Apple's code, but I'd assume that passing a double to numberWithInt: will return nil because a double is not an int.

Jasarien
the reason why i multiply it is because the slider needs to define how much space my app may use, which is defined in bytes in my case, but i need it in GB 1 byte times 8589934592 equals to 1GB. then i compare the folder size (which is also in bytes so i need to multiply it again) with the slider one to see if the limit has been reached or not. What should I use instead of setIntegerForKey? just use setObjectForKey?
David Schiefer
objectForKey won't work...
David Schiefer
I would suggest creating an `NSNumber` object from your final double value, using `numberWithDouble:` and then using `setObject:forKey`.
Jasarien
`setInteger` takes an NSInteger. I'm pretty sure the compiler should do the cast automatically; the object will *not* receive a double. It may not be great form to not make it explicit, but I don't think it's an error.
walkytalky
What walky said - you don't have to know Apples code for that, its a *language* feature.
Georg Fritzsche
the compiler shows no warning at all, i tried creating my own subclass `-(void)setDouble:(double)dou forKey:(id)key` and `-(double)doubleForKey:(id)key` but it still has the same result, even if i used NSNumber
David Schiefer
David Schiefer: 1 GB is 1,000,000,000 (10^9) bytes, particularly on Snow Leopard, where the Finder now follows this definition. Even on previous versions of Mac OS X and on other OSs, 1 GB (or GiB) has never been 8,589,934,592 bytes; the correct definition was 1024 * 1024 * 1024 = 1,073,741,824 bytes.
Peter Hosey
thanks for that Peter, I've changed my bytes value with your equation instead. could anyone suggest to me why even my custom NSUserDefaults implementation fails too? the odd thing is that when i want to update the NSSlider, it mysteriously works? `[sizeSlider setDoubleValue:[[NSUserDefaults standardUserDefaults] doubleForKey:@"BackUpSize"]/ 1024 / 1024 / 1024];` works fine :/
David Schiefer
+1  A: 

8589934592 is a hard-coded literal? Really? You should at least put something like 1 << 33. Even then, declare it as a constant, for crying out loud.

If you're building for 32 bit, NSInteger is a 32 bit signed value. So you are rather likely to be overflowing. I'm not sure what the behaviour of NSUserDefaults would be in that case, but it's worth considering.

walkytalky
I'm impressed that you recognized it as 1 << 33 on sight. ☺
Peter Hosey