Storing ints in a Dictionary - iphone

As I understand, in Objective-C you can only put Objects into dictionaries. So if I was to create a dictionary, it would have to have all objects. This means I need to put my ints in as NSNumber, right?
SOo...
NSNumber *testNum = [NSNumber numberWithInt:varMoney];
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init];
[dictionary setObject:#"OMG, Object 1!!!!" forKey:#"1"];
[dictionary setObject:#"Number two!" forKey:#"2"];
[dictionary setObject:testNum forKey:#"3"];
NSNumber *retrieved = [dictionary objectForKey:#"3"];
int newVarMoney = [retrieved intValue];
Where varMoney is an int that has been declared earlier. My question is, is there a better way to store "int" in a dictionary than putting it into a NSNumber?
Thanks!
Edit: 04/25/13
It's been a long time since I asked this question. For people stumbling on it in the future, there are easier ways to do this with the Apple LLVM Compiler 4.0, which has been default in Xcode for a bit. (ARC)
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[dictionary setObject:#1337 forKey:#"1"];
That's it, use the #1337 Syntax to quickly create NSNumber objects. Works with Variables, so my above could become:
[dictionary setObject:#(varMoney) forKey:#"3"];
or
dictionary[#"mykey"] = #1337;
Simpler.

You are correct, NSNumber is the normal way to handle this situation. You can use NSValue or NSDecimalNumber, too.

If you are prepared to fall back to using Core Foundation (CFDictionaries) you can store anything you like. I've definitely made dictionaries into which I put arbitrary void* values.
You need to do a little more plumbing but not much, and its all documented.

Sorry but no :( Not as far as I know. Reason being that integers aren't objects, and NSDictionary only stores objects.

Related

Mutable deep-copy of a NSMutableDictionary

First of all I found something similar:
deep mutable copy of a NSMutableDictionary
but it didn't solve my problem.
I have a NSMutableDictionary as a template.
NSMutableDictionary *mutableDictionaryTemplate = [NSMutableDictionary dictionaryWithObjectsAndKeys: #"obj1, #"key1",#"obj2, #"key2",nil];
Now I would like to copy this dictionary, then change some parts and later save it in a NSMutable Array.
NSMutableArray *savedIterations = [NSMutableArray new];
//some loop that normally would change the objects added
int i=0;
for (i < 5){
NSMutableDictionary *copiedDictionary = [mutableDictionaryTemplate copy];
[copiedDictionary setObject:#"obj3" forKey:#"key3"];
[savedIterations addObject:copiedDictionary];
i++;
}
My problem is that once I copy the NSMutableDictionary "mutableDictionaryTemplate" it no longer is mutable. But I need to copy it because otherwise I will have the same NSMutableDictionary at every index of my NSMutableArray "savedIterations" (at least I think so). I tried mutable copy as well but there I change the "mutableDictionaryTemplate" when I change "copiedDictionary". I think I have something messed up with what I have to copy and what not and how to copy it correctly.
It would be great if someone could point me into the right direction.
You could try this:
NSMutableDictionary *destinationDictionary = (NSMutableDictionary *)CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (__bridge CFPropertyListRef)(sourceDictionary), kCFPropertyListMutableContainers));

NSDictionary Memory leaks

I implement a method to return a dictionary in my app. But I find a memory leak using instrument, I tried to figure it out, but I still cannot find it. Can anyone help me out?
Thanks in advance, here is the code for that methods:
-(NSMutableDictionary *)initDict
{
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
[dict setObject:self.name forKey:#"Name"];
//Some similar set object for key here...
return dict;
}
I think the problem is from allocing memory for dict and not releasing it. But in the method, it seems I cannot release dict. So is there any method to fix the leak?
All variants are good. Here is third variant (choose wisely):
Replace
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
with
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
I think you just need to change the last line of initDict to this:
return [dict autorelease];
When you are creating any object in your function and you want to return them then you should always create it in a way that those objects are autoreleased. So you should change your code like below.
NSMutableDictionary *dict = [[[NSMutableDictionary alloc]init]autorelease];
So whenever you create any object just call autorelease method on that.

How do I archive an NSArray of NSDictionary (with NSCoding)?

Suppose I am holding data in an array like this
wordList = [[NSMutableArray alloc] init];
while ([rs next]) //Some database return loop
{
wordDict = [[NSMutableDictionary alloc] init];
[wordDict setObject:[NSNumber numberWithInt:[rs intForColumn:#"id"]] forKey:#"id"];
[wordDict setObject:[rs stringForColumn:#"word"] forKey:#"word"];
[wordList addObject: wordDict];
[wordDict release];
wordDict = nil;
}
But I want to store this result (i.e. wordList) in SQLite for later use - I guess using NSCoding. How would I do that?
(Feel free to point out any errors in how stuff is being alloc'ed if there are problems there).
If you don’t insist on serialization using NSCoding, there’s a writeToFile:atomically: method both on NSArray and NSDictionary. This will serialize your object into a property list (*.plist). The only catch is that all the objects in the “tree” to be serialized must be NSString, NSData, NSArray, or NSDictionary (see the documentation). I’m not sure how NSNumber fits in, but with a bit of luck it will be serialized and deserialized too. The inverse method that will turn the file back into a dictionary or an array is called initWithContentsOfFile:.
As for your code, I would just use the [NSMutableDictionary dictionary] convenience method that gets you an autoreleased dictionary. It’s shorter than the usual alloc & init and you save one line for the explicit release.

Mutable Object within an Immutable object

Is it acceptable to have a NSMutableArray within an NSDictionary? Or does the NSDictionary also have to be mutable?
The NSMutableArray will have values added to it at runtime, the NSDictionary will always have the same 2 NSMutableArrays.
Thanks,
Dan
Yes, it's perfectly acceptable. Keep in mind, the contents of the array are the pointers to your NSMutableArrays--those are what can't change in the immutable dictionary structure. What the pointers point to can change all you want. To wit:
NSMutableArray *arr = [[NSMutableArray alloc] init];
NSDictionary *dict = [NSDictionary dictionaryWithObject:arr forKey:#"test"];
[arr addObject:#"Hello"];
NSString *str = [[dict objectForKey:#"test"] objectAtIndex:0];
NSLog("%#", str);
It's quite acceptable. But, it's precisely the sort of setup that suggests you should seriously consider replacing the dictionary with an NSObject subclass that sports two properties for accessing the arrays.

How to create an NSMutableArray of floating point values

I'm new to Objective-C and iPhone development, and I'm trying to store floating-point values in an NSMutableArray, but when I do I get an error saying "incompatible type for argument 1 of 'addObject". What am I doing wrong? I'm trying to create an array of doubles that I can perform math calculations with.
NSMutableArray only holds objects, so you want an array to be loaded with NSNumber objects.
Create each NSNumber to hold your double then add it to your array. Perhaps something like this.
NSMutableArray *array = [[NSMutableArray alloc] init];
NSNumber *num = [NSNumber numberWithFloat:10.0f];
[array addObject:num];
Repeat as needed.
Use an NSNumber to wrap your float, because the dictionary needs an object:
[myDictionary setObject:[NSNumber numberWithFloat:0.2f] forKey:#"theFloat"];
/* or */
[myDictionary setObject:#0.2f forKey:#"theFloat"];
retrieve it by sending floatValue:
float theFloat = [[myDictionary objectForKey:#"theFloat"] floatValue];
Code is untested.
You can wrap many other data types in NSNumber too, check the documentation. There's also NSValue for some structures like NSPoint and NSRect.
In Cocoa, the NSMutableDictionary (and all the collections, really) require objects as values, so you can't simply pass any other data type. As both sjmulder and Ryan suggested, you can wrap your scalar values in instances of NSNumber (for number) and NSValue for other objects.
If you're representing a decimal number, for something like a price, I would suggest also looking at and using NSDecimalNumber. You can then avoid floating point inaccuracy issues, and you can generally use and store the "value" as an NSDecimalNumber instead of representing it with a primitive in code.
For example:
// somewhere
NSDecimalNumber* price = [[NSDecimalNumber decimalNumberWithString:#"3.50"] retain];
NSMutableArray* prices= [[NSMutableArray array] retain];
// ...
[prices addObject:price];
NSMutableArray *muArray = [[NSMutableArray alloc] init];
NSNumber *float = [NSNumber numberWithFloat:210.0f];
NSNumber *float1 = [NSNumber numberWithFloat:211.0f];
[muArray addObject:float];
[muArray addObject:float1];
NSlog(#"my array is--%#",muArray);