views:

535

answers:

4

In the following am I right (keeping in mind the NSNumber is an object) to use assign with NSNumber?

@property(assign) NSNumber *mass;

Also if I used retain I would need to add a release, but if I created the NSNumber with an alloc would I not need to release twice, once for retain and once for alloc?

@property(retain) NSNumber *mass;
mass = [[NSNumber alloc] numberWithInt:5];

gary

+4  A: 

You usually want to retain your instance variables, so they don't vanish on you unexpectedly. Your line:

mass = [[NSNumber alloc] numberWithInt:5];

is a little weird. You probably want one of these:

mass = [NSNumber numberWithInt:5];
mass = [[NSNumber alloc] initWithInt:5];

The first gives you back an autoreleased NSNumber object, the second one an NSNumber that has been retained. What I expect you are really looking for is this:

@property(retain) NSNumber *mass;
self.mass = [NSNumber numberWithInt:5];
Carl Norum
Heh - just posted my own take. I think it's important to point out that [[NSNumber alloc] numberWithInt:5] isn't just "weird", it's outright wrong.
Joshua Nozzi
I was kind of hoping it was a copy/paste/rewrite-on-stack-overflow problem, not the real code. You're right that it's wrong; I wonder if it even compiles?
Carl Norum
And the answer is yes, it compiles, not even a warning in my test. It crashes at runtime with NSInvalidArgumentException.
Carl Norum
A: 

You can use assign, however you need to be careful that some other class needs to retain it and that the class that handed it over needs to set it nil when releasing the NSNumber object.

If you make it a retain property, and you can write the following which will let the property have a retainCount of 1:

self.mass = [NSNumber numberWithInt:5];

or

mass = [[NSNumber alloc] initWithInt:5]; 
// no "self." also note that the message is "init..."

or

NSNumber *num = [[NSNumber alloc] initWithInt:5];
self.mass = num;
[num release];

Setting a retain-property only increase the retainCount if it set via "instance." or "self.".

Felix
same holds true for all objectsalso remember to release mass in the dealloc method of "self"
Felix
+1  A: 

Your confusion stems from two separate concepts: Objective-C 2.0 properties and memory management.

Whether to use assign or retain depends entirely on what you're trying to do and whether you're using garbage collection. If you're not using garbage collection, for example, and you were using assign, then set mass to [NSNumber numberWithInt:0], your (autoreleased) NSNumber instance would go away and you'd have problems next time you tried to use it.

Regarding how many releases you need in the second code block, you truly need to (re)read the memory management documentation. If you created the object (through the methods mentioned in the docs), you're responsible for releasing it. That's it. Whether something else retains it or not is "none of your business". So, following that logic, if your mass property retains (and properly releases) its value (and it will if you use @synthesize or follow proper accessor setter examples), it's handling its own business just fine. Again, if you create the object, you're responsible for releasing it. Others may retain/release the object as needed but that's beyond your concern.

Also, [[NSNumber alloc] numberWithInt:5] is wrong. You alloc/init... but you don't alloc, then call a convenience method (that presumably will alloc/init... an instance itself).

Joshua Nozzi
Thank you Joshua, I am on my 2nd reading of the memory management guide, but being new to Objective-C and Cocoa its taking a bit to sink in. Many thanks for your clear answer, I will have another read to refresh my knowledge based on where I am now.
fuzzygoat
It's difficult to get over the initial hump. Once you "get it" though, it becomes easy in most every case.
Joshua Nozzi
Moreover, `numberWithInt:` is a class method; sending that message to result of `alloc` is sending it to an *instance*.
Peter Hosey
A: 

NSNumber, and other immutable objects should be @property(retain) NSNumber *mass; (mutable objects should use copy)

when assigning use self.mass = [NSNumber numberWithInt:5];. Since the method doesn't contain new, copy, init, it returns an autoreleased object. Using self. will call the setter and retain the value.

Read the Memory management rules.

Jason Harwig