views:

157

answers:

1

I'm just getting started with using threads in obj-c/cocoa and I'm running into some trouble.. I get this error in the console:

2010-02-15 09:18:41.467 Timer[1007:4503] *** __NSAutoreleaseNoPool(): Object 0x10012adc0 of class __NSCFDate autoreleased with no pool in place - just leaking 2010-02-15 09:18:41.478 Timer[1007:4503] *** __NSAutoreleaseNoPool(): Object 0x1003362b0 of class NSCFTimer autoreleased with no pool in place - just leaking here is the code that creates the new thread:

    // Timer
JHTimer *timer = [[JHTimer alloc] init];
[timer setMinTextLabel:minTextLabel];
[timer setSecTextLabel:secTextLabel];
[timer setHrTextLabel:hrTextLabel];
timerTimeInt = 30;
[timer setTimerInterval:timerTimeInt];
[NSThread detachNewThreadSelector:@selector(start) toTarget:timer withObject:nil];

and the code that creates the autorelease pool (and the start method that creates the timer):

- (void)main {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
}

- (void)start {
    timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerDidUpdate:) userInfo:nil repeats:YES];
    NSLog(@"Test");
}

and I can't figure out that's wrong

+3  A: 

Where is your JHTimer's main being invoked from? You need to create the autorelease pool in the method for the selector you provide to detachNewThreadSelector:toTarget:withObject: as it says in the documentation.

For non garbage-collected applications, the method aSelector is responsible for setting up an autorelease pool for the newly detached thread and freeing that pool before it exits. Garbage-collected applications do not need to create an autorelease pool.

dreamlax
Thanks, works great.... but the NSTimer isn't running
nanochrome
@nanochrome: I think that creating an NSTimer, even in another thread, will still cause the firing events to occur in the main thread because it is scheduled in the *current* run loop. If you have started another thread, it may be more advantageous to simply sleep the thread with `[NSThread sleepForTimeInterval:1];`.
dreamlax
I don't quite understand....
nanochrome
Rather than having a timer on a secondary thread, just paste the contents of your `timerDidUpdate:` method into a `while(1)` loop in your `start` method, but add `[NSThread sleepForTimeInterval:1];` at the end of it.
dreamlax
dreamlax: “Current” does not mean “main” except on the main thread. nanochrome is creating and scheduling the timer on the secondary thread; therefore, the current run loop there is the secondary thread's run loop; therefore, the timer will be on that run loop, not the main one.
Peter Hosey
nanochrome: You're doing it right. You are scheduling the timer on the secondary thread's run loop, not the main thread's.
Peter Hosey
Ah of course, what was I thinking? Perhaps then, is it possible that the timer never fires because the thread itself is not alive after the `start` method returns?
dreamlax
The `start` method needs to hand over control to the thread's run loop in order for the timer to fire (and in order to keep `start` from returning, which will end the thread). The simplest way to do this (after you've set up the NSTimer) is to call: `[[NSRunLoop currentRunLoop] run];`. The `run` method won't terminate (return) until the app exits, so if you need your thread to stop before then, use one of NSRunLoop's other run methods (`runMode:beforeDate:`, `runUntilDate:`).
tedge