PDA

View Full Version : Retain counts on [NSTimer scheduledTimer]/etc




Thomas Harte
Oct 21, 2009, 09:09 AM
Hi, sorry, can't seem to find an answer to this.

What is the convention with retain counts for objects that exist to push something into the runloop later on (such as a scheduled timer or an asynchronous data fetch) which are created through the non-alloc/init routes?

I'm aware that when you do something like:
NSString *string = [NSString stringWithFormat:@"Some text"];

"string" is in the autorelease pool, so to be treated broadly as though it's a value the stack.

Therefore, if it follows the ordinary conventions then something like:
NSTimer *timer = [NSTimer scheduledTimerWithInterval:...];

Will return a timer that isn't guaranteed to fire, since it may be released at any point after execution has gone back to the runloop.

A broadly similar question: what is the correct response when receiving the final delegate callback from an object that I created? Such as, for example, in:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection

I've been treading cautiously and calling [connection autorelease] (so it'll be released at some point definitely after whatever method it may be in to call me has completed safely), is that the normal thing to do?



whooleytoo
Oct 21, 2009, 09:47 AM
When the timer is added to the run loop, it's retained. If you invalidate the timer, it's released. So no, you don't have to retain the timer in order for it to fire. As a matter of habit, I always retain every timer, in case I need to invalidate it at a later point, but YMMV.

If I understand the second question correctly, you're asking if you can release an object, a method of which is in the current stack (i.e. one of that object's methods is directly or indirectly calling a method which releases that object). I don't THINK that's safe, but generally I avoid it too. I used to use NSRunLoop's performSelector.. method to do a deferred release; but autorelease is probably simpler and more legible.

kainjow
Oct 21, 2009, 11:27 AM
I've never seen a crash where a timer wasn't retained, but it's good habit to retain it to stick with Cocoa conventions.

As for releasing objects in delegate methods, I've never had issue doing this with Apple's classes, even with your NSURLConnection example. I *have* had problems with my own but that was because I would setup my class to call the delegate method, and then the class might continue to do something else. If the delegate calls release then ivars may be corrupt and that could cause crashes. So when writing your own classes you should always makes sure that when calling the delegate in finish-like methods that your class doesn't do anything else afterwards.