Pages

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'];

47 comments:

  1. 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

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

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

    ReplyDelete
  4. 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

    ReplyDelete
  5. 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

    ReplyDelete
  6. 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

    ReplyDelete
  7. It is amazing and wonderful to visit your site.Thanks for sharing this information,this is useful to me...
    python training in rajajinagar | Python training in btm | Python training in usa

    ReplyDelete
  8. I really thank you for your innovative post.I have never read a creative ideas like your posts.here after i will follow your posts which is very much help for my career.
    Java Certification course in Bangalore
    Java Courses in Nolambur
    Java Training in Ashok Nagar
    Java Training in Kelambakkam

    ReplyDelete
  9. indeed, I’m just always astounded concerning the remarkable things served by you. Some four facts on this page are undeniably the most effective I’ve had.
    SOFTWARE TRAINING IN CHENNAI
    POWERBI TRAINING IN CHENNAI
    CCNA TRAINING IN CHENNAI
    ANDROID TRAINING IN CHENNAI

    ReplyDelete
  10. QuickBooks Desktop Tech Support Phone Number - With the latest software release of QuickBooks Desktop 2019, it has successfully outgrown other business software products in the competitive market. QuickBooks Desktop gives you the flexibility to manage your accounting, inventory, point of sale, payroll, payment and increase your productivity. It also allows you to track items, vendors and customers.

    QuickBooks POS Tech Support Phone Number | QuickBooks Payroll Tech Support Phone Number

    ReplyDelete
  11. Thank you for sharing such a nice post!

    Softgen Infotech is the Best HADOOP Training located in BTM Layout, Bangalore providing quality training with Realtime Trainers and 100% Job Assistance.

    ReplyDelete
  12. Data Science Course in Hyderabad by AI Patasala will be an ideal opportunity to get to know every Concept of Data Science with live demonstrations, real-time scenarios, and examples taught by experts.
    Data Science Course in Hyderabad
    Data Science Training in Hyderabad

    ReplyDelete
  13. wow really good informision got lot to learn. looking forward for more informative posts from you.
    French Online Course | French Language Course | Online French Courses

    ReplyDelete
  14. Great Blog.Thanks for sharing such a wonderful blog.
    AWS classes in Pune

    ReplyDelete
  15. It's interesting how many of the bloggers helped me clarify a few things while also giving.The majority of ideas can be good material.Give them a good shake to get your point through and the demand across.
    https://edit.co.in/ui-ux-design-course-in-bangalore.html

    ReplyDelete
  16. amazing writeup, keep posting and checkout our blog aws training in pune

    ReplyDelete
  17. Excellent post! Dealing with NSTimer in unit tests can be challenging, but your approach simplifies it considerably. The step-by-step breakdown makes it easy to grasp how to properly wait for the timer to finish during tests without blocking the main thread. It’s a smart solution to a common issue when testing timed events. I’m curious if you’ve encountered any challenges or pitfalls with this method in more complex timing scenarios. Thanks for sharing such a valuable guide!"


    Digital Marketing Course In Ameerpet

    ReplyDelete
  18. Great post! Handling NSTimer in unit tests can be tricky, and your approach makes it much clearer. The step-by-step explanation really helps to understand how to effectively wait for the timer to complete during tests without blocking the main thread. It’s a clever solution to a common problem in testing timed events. I’d be curious to know if you’ve come across any potential pitfalls when using this method for more complex timing scenarios. Thanks for sharing this valuable guide!"


    Digital Marketing Course In Hyderabad

    ReplyDelete
  19. This comment has been removed by the author.

    ReplyDelete
  20. FlyzGlobal is recognized as one of the best immigration consultants in Chennai, providing reliable and efficient visa services for study, work, PR, and visitor visas. With experienced consultants, tailored solutions, and a transparent approach, FlyzGlobal ensures a hassle-free process for all your immigration needs. Trust FlyzGlobal to guide you toward achieving your dreams of living, studying, or working abroad.

    ReplyDelete
  21. SailPoint Training in Hyderabad – Procode Technologies

    Looking for the best SailPoint training in Hyderabad ? Procode Technologies offers industry-standard training with hands-on experience, real-time projects, and expert instructors. Whether you're a beginner or looking to upskill, this course is designed to make you job-ready in the Identity and Access Management (IAM) domain.

    Why Choose Procode Technologies?

    Expert Trainers with real-time experience

    100% Placement Assistance

    Weekend & Weekday Batches

    Certification Support

    Access to Recorded Sessions

    For more details and enrollment, contact Procode Technologies today and kickstart your career in IAM with SailPoint!

    ReplyDelete