PDA

View Full Version : Chapter 8 Hillegass Question




isharan
Jun 11, 2009, 09:59 PM
I'm working through Aaron Hillegass' Cocoa Programming for Mac OS X 3rd Edition and have a question on Chapter 8 (NSArrayController) In MyDocument.m, in the dealloc method, instead of releasing the employees array, its instead set to nil. What's the reasoning behind this?

- (void)dealloc
{
[self setEmployees:nil];
[super dealloc];
}



HiRez
Jun 11, 2009, 10:53 PM
The reason this is done is that it's a little safer than outright releasing the object. If you send an explicit release message to an object that's already been deallocated, your app will crash. I know, you're probably thinking "But I should already know if my object is valid or not when dealloc is called!", and you should know, but trust me, you won't when your app gets any kind of complexity.

Generally in your accessor you will check the existence of an object and then release the object before assigning a new one, so if you send nil to the accessor (setter), it will first check for you that your object exists, and then release it for you. You could just duplicate the code in dealloc, but since your accessor probably has it anyway already (make sure!), you might as well reuse it.

Note that you need to be careful here that you're not doing anything else in your setter method, like working on some other objects that may have already been deallocated when called from the dealloc method. Generally a straight setter will look something like this:

- (void)setName:(NSString *)newName {
if (name != nil) {
[name release];
name = nil;
}
name = [newName copy];
}

Catfish_Man
Jun 11, 2009, 11:57 PM
Messaging nil is safe, so that's really not that necessary. Also you want to avoid accidentally triggering KVO notifications while deallocating.

idelovski
Jun 12, 2009, 03:18 AM
You guys conspired to unnecessarily confuse me, so I had to look what the book says.

Setter method is just a few millimeters below -dealloc and there's a comment that should give us a clue:

Hillegass: "This is an unusual setter method. We are going to add a lot of smarts to it in the next chapter."

jared_kipe
Jun 12, 2009, 03:53 AM
Out of curiosity, does anyone write accessor methods anymore? I haven't come across something I couldn't do with @property/@sythesize

I usually use @property (retain, nonatomic) for the vast majority of objects and @property (assign, nonatomic) for normal datatypes.

I find (retain, nonatomic) works particularly well with convenience methods like [NSString stringWithFormat: @"%0.2f", someDouble]


Off topic. Today I found myself calculating something in a double and then wanting to carry out another computation on fixed precision form of that double, like say to 2 decimal places. So I basically did this.
fixedDouble = [[NSString stringWithFormat: @"%0.2f", someDouble] doubleValue];

Is there an easier way? Assuming I have to put both the someDouble and fixedDouble through some calculations for instance <math.h>'s acos(); function?

autorelease
Jun 12, 2009, 04:24 AM
Is there an easier way? Assuming I have to put both the someDouble and fixedDouble through some calculations for instance <math.h>'s acos(); function?

Multiply the number by 100, round it to a whole number (the choice of round(), trunc(), etc. is up to you), then divide it by 100.

Note that there's no way to "exactly" round a floating-point number to a set number of decimal places, there will often be some error because not all numbers can be represented exactly by a float. For example, 3.10 is actually stored as something like 3.099999904633.

This is also why you should never use floats for monetary quantities.

GorillaPaws
Jun 12, 2009, 05:04 AM
This is also why you should never use floats for monetary quantities.

It is my understanding that NSDecimalNumber is the proper class when dealing with money. At least that's what Marcus Zarra said in his article (http://www.cimgf.com/2008/04/23/cocoa-tutorial-dont-be-lazy-with-nsdecimalnumber-like-me/) on the subject.

jared_kipe
Jun 12, 2009, 12:32 PM
Multiply the number by 100, round it to a whole number (the choice of round(), trunc(), etc. is up to you), then divide it by 100.

Note that there's no way to "exactly" round a floating-point number to a set number of decimal places, there will often be some error because not all numbers can be represented exactly by a float. For example, 3.10 is actually stored as something like 3.099999904633.

This is also why you should never use floats for monetary quantities.

I realize that, but I'm working on something where someone is expected to calculate something and see if they agree on the computer's result. The user will not even be shown the whole double, so in certain cases they would get widely different results than the computer if the computer used the whole number for the calculation. So far it is working perfectly, but I do believe this carries less overhead. So thank you.

Second off topic. Say I need to pause my iPhone app for say 400ms or so while something is displayed, then trigger a method. How would I setup this seemingly easy delay?

autorelease
Jun 12, 2009, 01:35 PM
Second off topic. Say I need to pause my iPhone app for say 400ms or so while something is displayed, then trigger a method. How would I setup this seemingly easy delay?

NSTimer. Or usleep(), if you don't mind blocking the main thread.

HiRez
Jun 12, 2009, 01:53 PM
Second off topic. Say I need to pause my iPhone app for say 400ms or so while something is displayed, then trigger a method. How would I setup this seemingly easy delay?I would use NSObject's performSelector:withObject:afterDelay: I'm not sure this is available on iPhone, but I assume it is.

jared_kipe
Jun 12, 2009, 07:17 PM
performSelector: worked beautifully thank you