Your statement:
[NSTimer scheduledTimerWithTimeInterval:10
target:self
selector:@selector(loopTest:)
userInfo:nil
repeats:NO];
does not delay your loop - rather for every iteration of the loop it schedules a timer to call loopTest:
, a method you've defined to do nothing.
To use a timer to delay a loop you need to schedule a method which performs the remainder of the loop. In other words a non-loop method which performs the equivalent of one iteration of your loop and then schedules a time to perform the remainder.
Following your approach, but switching to use an implicit timer provided by performSelector:withObject:afterDelay
as it is more convenient here, this gives us:
- (IBAction)beginLoop:(id)sender
{
// start "loop"
// note we only pass the current index and not the limit or delay
// as there is no performSelector version which directly supports
// passing three values to the selector
[self doLoopIndex:@0];
}
- (void) doLoopIndex:(NSNumber *)objIndex
{
// extract int from NSNumber - we use the later as the argument type so we can use performSelector below
int index = objIndex.intValue;
// do the work of one iteration
NSString *feed = [NSString stringWithFormat: @"%d", index];
self.feedLabel.stringValue = feed;
// increment "loop" counter and schedule next iteration if needed
// note the use of @(index) to create an NSNumber as an object is required
index++;
if (index < 100)
[self performSelector:@selector(doLoopIndex:) withObject:@(index) afterDelay:1];
}
This is not the only way to achieve your goal. Using blocks and "Grand Central Dispatch" (GCD) is another and in this case has the advantage that passing three values: current index, limit and delay; is easier.
For example, a general loop with delay might be written as:
- (void) doLoop:(int)index // starting index
limit:(int)limit // limit
delay:(NSTimeInterval)delayInSeconds // delay each iteration
body:(void (^)(int))body // block for loop body
{
// invoke the body block
body(index);
// increment index and schedule next "iteration" if needed
index++;
if (index < 100)
{
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void)
{
[self doLoop:index limit:limit delay:delayInSeconds body:body];
});
}
}
See the documentation for the details of the dispatch_X methods and types.
This might look more complicated, but that is because it is more general. Using the above your particular loop becomes just:
- (IBAction)beginLoop:(id)sender
{
[self doLoop:0 limit:100 delay:1 body:^(int index)
{
NSString *feed = [NSString stringWithFormat: @"%d", index];
self.feedLabel.stringValue = feed;
}];
}
Which of the above approaches, or using an explicit timer as your original code did, is appropriate for your use case is your choice - there is no single "right" answer.
HTH.