venerdì 4 marzo 2011

How to execute a NSTimer from NSThread

Few days ago I run into a problem related to user interaction on UIPickerView and a NSTimer. When the user interact with UIPickerView the NSTimer is delayed. That is obvious but really annoying.
I found a partial solution Naren blog, but unfortunately it is incomplete. I would like to stop and restart the NSTimer many times and with Naren's code there is a memory leak (NSThread).

The the final solution is the following:

@interface Test : NSObject
     NSTimer *_timer;
     NSRunLoop *_runLoop;
     NSThread *_timerThread;

- (void)suspendTimer;
- (void)resumeTimer;
- (void)timerFireMethod:(NSTimer*)timer;

@end // End Test interface

@implementation Test

- (void)suspendTimer
     if(_timer != nil)
          [_timer invalidate];
          [_timer release];
          _timer = nil;

          CFRunLoopStop([_runLoop getCFRunLoop]);

          [_timerThread release];
          _timerThread = nil;

- (void)_startTimerThread
     NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

     _runLoop = [NSRunLoop currentRunLoop];
     _timer = [[NSTimer scheduledTimerWithTimeInterval:1.0
          repeats:YES] retain];
     [_runLoop run];
     [pool release];

- (void)resumeTimer
     if(_timer == nil)
          _timerThread = [[NSThread alloc] initWithTarget:self
          [_timerThread start];

- (void)timerFireMethod:(NSTimer*)timer
     // ...

@end // End Test implementation

For some strange reason NSRunLoop class doesn't provide an API to stop the run loop. The trick is to convert NSRunLoop into CFRunLoop and stop it.

In NSRunLoop class description is specified that the methods are not thread safe. I didn't experienced any problems with this implementation. As alternative the code above can be completely written using CFRunLoop type and functions:

  • [NSRunLoop currentRunLoop] -> CFRunLoopCurrent()
  • NSRunLoop * -> CFRunLoopRef
In CFRunLoop documentation I didn't found any thread safety warning.

Enjoy !


2 commenti:

  1. Thank you, I had an issue in updating the audio player's duration (through UISlider in UITableViewCell). You code resolved the issue and saved time.

  2. Se cerchi un prodotto eccezionale... devi andare in un posto eccezionale. Scopri il test. Vai su