by ampatspell
in Code
Here is tiny macro what runs NSRunLoop with step of 0.1 second until some condition is met. Useful for NSRunLoop dependent unittests:
#define kRunLoopTestTimeout 10.0 #define AMRunWhile(expr) { \ NSDate *start = [NSDate date]; \ do { \ [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow: 0.1]]; \ } while ((expr) && ([start timeIntervalSinceNow] > -kRunLoopTestTimeout)); \ STAssertTrue(!(expr), @"Loop timeout for %@", [NSString stringWithUTF8String: #expr]); \ }
Usage example in OCUnit test case:
- (void)testShouldWaitUntilTimerFinishes { Something *something = [[Something alloc] init]; [something start]; // should set finished later. see example implementation. STAssertFalse([something finished], nil); // wait until finished AMRunWhile([something finished] == NO); // this is not necessary in actual unittest STAssertTrue([something finished], nil); [something release]; }
And there is Something implementation with NSTimer:
@implementation Something @synthesize finished; - (id)init { if(self = [super init]) { finished = false; } return self; } - (void)start { // adds timer what will call -finish after one second NSTimer *timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(finish) userInfo:nil repeats:NO]; [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; } - (void)finish { self.finished = YES; } @end