1

I have been having some crashes in my app. When checking the logs and using atos, it is telling me exactly where I get the crash, which is where I tell my NSRunLoop to run:

/**
 * Create a new thread for the timer
 *
 * @version $Revision: 0.1
 */
- (void)createTimerThread {
    NSThread *timerThread = [[NSThread alloc] initWithTarget:self selector:@selector(startTimerThread) object:nil];
    [timerThread start];
    [timerThread release];
}//end


/**
 * Start the actual timer
 *
 * @version $Revision: 0.1
 */
- (void)startTimerThread {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];

    // Start timer
    self.countTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateCounter:) userInfo:nil repeats:YES];

    [runLoop run];// <--- Crash happened here
    [pool release];

}//end


/**
 * Update the counter
 *
 * @version $Revision: 0.1
 */
- (void)updateCounter:(NSTimer *)theTimer {

    // Does tons of timer stuff here

}//end

As you can see, the crash happens on [runLoop run] but I have no idea why. It normally happens the second time that I call the createTimerThread method.

What am I doing wrong here? All I was wanting to do was run a timer in the background so that it wasn't on the main thread because I needed to update a UILabel.

Should I be using something new like Grand Central Dispatch (GCD)?

Nic Hubbard
  • 41,587
  • 63
  • 251
  • 412
  • Enable NSZombies and then you'll find out why. EXC_BAD_ACCESS is to do with something being released which shouldn't a.k.a a zombie is on the loose. – max_ Oct 17 '11 at 01:12
  • Are you accessing your UILabel from within the background thread? Or any other UI element? – JustSid Oct 17 '11 at 01:24
  • I update the UILable in the updateCounter method. So, not sure if that now is in the background. – Nic Hubbard Oct 17 '11 at 01:30

2 Answers2

1

You said updateCounter is updating a UILabel and that's being called from the timer that's running on the background thread. You can't do that, you need to update UI views on the main thread.

You can either use performSelectorOnMainThread or GCD (dispatch to the main queue). I compared both using samples on this SO post:

GCD, Threads, Program Flow and UI Updating

This SO article specifically has an example of a bg timer with GCD:

iOS4 Create Background Timer

Look at the post from mrwalker

Community
  • 1
  • 1
bryanmac
  • 38,941
  • 11
  • 91
  • 99
0

Any calls that involve the UI are not thread safe, meaning you have to do any updates on the main thread.

Not sure what you are actually trying to achieve. If you are doing something computationally expensive on every timer "tick", then yes GCD would be you best bet utilizing blocks.

Perhaps you could give us some insight on what your doing each tick and what your displaying in the UILabel?

cocoahero
  • 1,302
  • 9
  • 12
  • It is just a simple timer that counts from 0. It updates the UILabel to show how much time has passed. The counter is created each time a new Core Data record is created. – Nic Hubbard Oct 17 '11 at 02:01
  • So each core data entity instance will have it's own timer? Perhaps a better approach is to set a "startTime" transient property on each entity instance. Then set a single timer that goes through each entity, calculating the elapsed time and updating the UILabel. – cocoahero Oct 17 '11 at 02:16