为什么你应该使用计时器
这样做的正确方法是使用重复计时器。计时器被配置为每秒重复并调用某个方法。
[NSTimer scheduledTimerWithTimeInterval:1.0
target:self
selector:@selector(updateText:)
userInfo:nil
repeats:YES];
在您的(新)updateText
方法中,您将生成随机数并更新文本。
- (void)updateText:(NSTimer *)theTimer {
int index = arc4random() % [myArray count];
myTextView.text = [myArray objectAtIndex:index];
}
这是一个几乎是自我记录的干净解决方案。
为什么你不应该在延迟后循环和执行。
确实可以performSelector:withObject:afterDelay:
使用or来执行此操作,dispatch_after()
但它很容易出错,并且实际的工作解决方案更复杂且更难理解。
如果你认为你可以循环一定次数并在内部调用其中任何一个,那么你会看到一些有趣的东西。这两种方法都是异步的,不会等待调用被调用。他们只是安排它从“现在”开始的指定时间发生。
循环和调用异步方法的作用
Loop
0 |----- 1s wait -----| |update|
1 |----- 1s wait -----| |update|
2 |----- 1s wait -----| |update|
3 |----- 1s wait -----| |update|
...
----------- time --------------------->
可以想象,这样做的结果是一秒钟内什么都不会发生。然后所有预定的呼叫将同时发生。
这实际上等于在一秒钟后执行整个循环。
|----- 1s wait -----| Loop:
0 |update|
1 |update|
2 |update|
3 |update|
...
----------- time --------------------->
如果您改为在每次更新后安排下一次通话,您就可以完成这项工作
|----- 1s wait -----| |update| |----- 1s wait -----| |update| ...
----------- time --------------------->
为此,您必须在上一次更新中安排下一次更新。
- (void)updateText {
int index = arc4random() % [myArray count];
myTextView.text = [myArray objectAtIndex:index];
[self performSelector:@selector(updateText)
withObject:nil
afterDelay:1.0];
}
这将做与重复计时器完全相同的事情,但有两个主要缺点。
1)它不太直观。
在计时器示例中,您只需阅读计时器代码即可了解文本每秒更新一次。在这种情况下,您只需调用updateText
. 通过阅读该代码而不查看 updateText 的实现是不直观的,这是一个重复的过程。
2)如果你想让它停止,它会变得更加复杂。
您可以保留一个指向 an 的指针,NSTimer
并通过简单地调用来使其停止[myTimer invalidate];
。使用performSelector:...
或dispatch_after()
尚不支持它的代码,如果它是为了支持它而构建的,它将更加复杂和不直观。