Sunday, October 16, 2011

How to wait while an NSTimer runs in a unit test

Suppose you were a lowly noob to iOS development. Further suppose you had a Cool Idea (tm) which involved timers. The internets might rapidly guide you to NSTimer and you might decide to try to get it to log to the console in a unit test. The most obvious approach seems to be to setup a timer to tick frequently, lets say every 0.1 seconds, and setup a timer callback that logs something, then make a test that sleeps for a couple of seconds. Presumably during the sleep period we'll see a bunch of timer output. The code might look like this (inside an XCode 4.2 test implementation class):

- (void)onTimerTick:(NSTimer*)timer
{
    NSLog(@"MY TIMER TICKED");
}

- (void)testTimerBasics
{
    NSLog(@"timer time");
    
    [NSTimer scheduledTimerWithTimeInterval:0.1
                   target:self
                   selector:@selector(onTimerTick:)
                   userInfo:nil
                   repeats:YES];
    
    [timer fire]; //manually calling fire DOES log 'MY TIMER TICKED'
    
    NSLog(@"about to wait");    
    [NSThread sleepForTimeInterval:2.0]; //absolutely no logs of 'MY TIMER TICKED' occur; somehow the time doesn't fire during a thread sleep :(
    NSLog(@"wait time is over");    
}

Sadly absolutely no log messages are printed during our two second sleep ([NSThread sleepForTimeInterval:2.0]) ; WTF?!

After much Google and literally in the midst of typing a Stack Overflow question I came across a question involving waiting for something else that mentioned NSRunLoop in passing. The very existence of a run loop class suggests an answer: our tests run on the same thread as the run loop. This means if we put the run loop to sleep nothing gets processed. Instead of sleep we need some sort of "run the run loop for a while" approach. Luckily it turns out that NSRunLoop provides a runUntilDate API so we can re-write the test above as follows:

- (void)onTimerTick:(NSTimer*)timer
{
    NSLog(@"MY TIMER TICKED");
}

- (void)testTimerBasics
{
    NSLog(@"timer time");
    
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.1
                              target:self
                              selector:@selector(onTimerTick:)
                              userInfo:nil
                              repeats:YES];
    
    //[timer fire];
    
    NSDate *runUntil = [NSDate dateWithTimeIntervalSinceNow: 3.0 ];
    
    NSLog(@"about to wait");    
    [[NSRunLoop currentRunLoop] runUntilDate:runUntil];
    NSLog(@"wait time is over");    
}
We've found the right magic incantation! Knuth would be proud.

Speaking of magic incantations, I am using the SyntaxHighlighter libraries hosted @ http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/. However, there is no Objectionable-C brush there so I took the one posted @ http://www.undermyhat.org/blog/wp-content/uploads/2009/09/shBrushObjectiveC.js and updated it the casing and namespace names to the newer highlighter standard. The updated brush looks like this:


dp.sh.Brushes.ObjC = function()
{
 var datatypes = 'char bool BOOL double float int long short id void';
 
 var keywords = 'IBAction IBOutlet SEL YES NO readwrite readonly nonatomic nil NULL ';
 keywords += 'super self copy ';
 keywords += 'break case catch class const copy __finally __exception __try ';
 keywords += 'const_cast continue private public protected __declspec ';
 keywords += 'default delete deprecated dllexport dllimport do dynamic_cast ';
 keywords += 'else enum explicit extern if for friend goto inline ';
 keywords += 'mutable naked namespace new noinline noreturn nothrow ';
 keywords += 'register reinterpret_cast return selectany ';
 keywords += 'sizeof static static_cast struct switch template this ';
 keywords += 'thread throw true false try typedef typeid typename union ';
 keywords += 'using uuid virtual volatile whcar_t while';
 // keywords += '@property @selector @interface @end @implementation @synthesize ';
 
  
 this.regexList = [
  { regex: dp.sh.RegexLib.SingleLineCComments,  css: 'comments' },  // one line comments
  { regex: dp.sh.RegexLib.MultiLineCComments,  css: 'comments' },  // multiline comments
  { regex: dp.sh.RegexLib.DoubleQuotedString,  css: 'string' },   // double quoted strings
  { regex: dp.sh.RegexLib.SingleQuotedString,  css: 'string' },   // single quoted strings
  { regex: new RegExp('^ *#.*', 'gm'),      css: 'preprocessor' },  // preprocessor
  { regex: new RegExp(this.GetKeywords(datatypes), 'gm'),  css: 'datatypes' },  // datatypes
  { regex: new RegExp(this.GetKeywords(keywords), 'gm'),  css: 'keyword' },   // keyword
  { regex: new RegExp('\\bNS\\w+\\b', 'g'),     css: 'keyword' },   // keyword
  { regex: new RegExp('@\\w+\\b', 'g'),      css: 'keyword' },   // keyword
  ];
 this.CssClass = 'dp-objc';
 this.Style = '.dp-objc .datatypes { color: #2E8B57; font-weight: bold; }'; 
}
dp.sh.Brushes.ObjC.prototype = new dp.sh.Highlighter();
dp.sh.Brushes.ObjC.Aliases  = ['objc'];

18 comments:

Naviya Nair said...

I have read your blog its very attractive and impressive. I like it your blog.

Java Online Training Java EE Online Training Java EE Online Training Java 8 online training Core Java 8 online training

Java Online Training from India Java Online Training from India Core Java Training Online Core Java Training Online Java Training InstitutesJava Training Institutes

Priya Kannan said...

It's interesting that many of the bloggers to helped clarify a few things for me as well as giving.Most of ideas can be nice content.The people to give them a good shake to get your point and across the command .
IOS Training in Chennai

Swathi Samala said...

very valuable information ios Online Training Bangalore

Unknown said...

Really Good blog post.provided a helpful information.I hope that you will post more updates like this
ios Online Training Hyderabad

soukya reddy said...

The information which you have provided is very good. It is very useful who is looking for ios Online Training Bangalore

likitha said...

I have read your blog its very attractive and impressive. I like your blog. ios Online course Bangalore

akhila priya said...

I really enjoy the blog.Much thanks again. Really Great ios Online Course Bangalore

SRI said...

Your good knowledge and kindness in playing with all the pieces were very useful. I don’t know what I would have done if I had not encountered such a step like this.

rpa Training in Chennai

rpa Training in bangalore

rpa Training in pune

blueprism Training in Chennai

blueprism Training in bangalore

blueprism Training in pune

rpa online training

digi mark said...

Great post! I am actually getting ready to across this information, It’s very helpful for this blog.Also great with all of the valuable information you have Keep up the good work you are doing well.

automation anywhere training in chennai

automation anywhere training in bangalore

automation anywhere training in pune

automation anywhere online training

blueprism online training

rpa Training in sholinganallur

rpa Training in annanagar

iot-training-in-chennai

shalinipriya said...

This is very good content you share on this blog. it's very informative and provide me future related information.
Data Science training in marathahalli
Data Science training in btm
Data Science training in rajaji nagar
Data Science training in chennai
Data Science training in kalyan nagar
Data Science training in electronic city
Data Science training in USA


simbu said...

This blog is the general information for the feature. You got a good work for these blog.We have a developing our creative content of this mind.Thank you for this blog. This for very interesting and useful.

java training in marathahalli | java training in btm layout

java training in jayanagar | java training in electronic city

java training in chennai | java training in USA

selenium training in chennai

pragya pragya said...

python training institute in chennai
python training in velachery
python training institute in chennai

shethal said...

This is most informative and also this post most user friendly and super navigation to all posts... Thank you so much for giving this information to me.. 
Devops training in velachery
Devops training in annanagar
Devops training in sholinganallur
Devops training in tambaram

param jothi said...

Great content thanks for sharing this informative blog which provided me technical information keep posting.
Blueprism training in Chennai

Blueprism online training

Blue Prism Training in Pune

chitra pragya said...

I think you have a long story to share and i am glad after long time finally you cam and shared your experience.

angularjs Training

in chennai

angularjs Training in chennai

angularjs-Training in tambaram

angularjs-Training in sholinganallur

angularjs-Training in velachery

cynthia williams said...

I have to thank for sharing this blog, it is really helpful.
RPA Training in Chennai
Robotics Process Automation Training in Chennai
RPA courses in Chennai
RPA Training
RPA course

Dwarakesh babu said...

I’m planning to start my blog soon, but I’m a little lost on everything. Would you suggest starting with a free platform like Word Press or go for a paid option? There are so many choices out there that I’m completely confused. Any suggestions? Thanks a lot.
Best AWS Training in Marathahalli | AWS Training in Marathahalli
Amazon Web Services Training in Anna Nagar, Chennai |Best AWS Training in Anna Nagar, Chennai
AWS Training in Velachery | Best AWS Course in Velachery,Chennai
Best AWS Training in Chennai | AWS Training Institutes |Chennai,Velachery

Vikky cmd said...

I am really happy with your blog because your article is very unique and powerful for new reader.
Click here:
selenium training in chennai
selenium training in bangalore
selenium training in Pune
selenium training in pune
Selenium Online Training

Post a Comment