循环更改文本字段仅显示一个最终值 [英] Changing text field repeatedly in a loop only displays one final value
问题描述
我希望创建一个循环,该循环每十秒递增一个整数,并执行一百次。但是当我使用以下代码时:
I wish to create a loop that increments an integer every ten seconds, and does this one hundred times. But when I use this code:
- (IBAction)loopTest:(id)sender {
}
- (IBAction)beginLoop:(id)sender {
for (i=0;i<100 ;i++ ) {
testingLoops++;
NSString *feed = [NSString stringWithFormat: @"%d", testingLoops];
self.feedLabel.stringValue = feed;
[NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(loopTest:) userInfo:nil repeats:NO];
}
}
应用程序仅将整数显示为马上100。我有它,这样当我按下按钮时它就会运行 beginLoop
。
the application just displays the integer as 100 straight away. I have it so that it runs the beginLoop
when I press a button. What's going on?
推荐答案
您的声明:
[NSTimer scheduledTimerWithTimeInterval:10
target:self
selector:@selector(loopTest:)
userInfo:nil
repeats:NO];
not 不会延迟循环-而是每次循环迭代安排计时器调用 loopTest:
,您已定义为什么都不做的方法。
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.
按照您的方法进行操作,但切换到使用由 performSelector:withObject:afterDelay
提供的隐式计时器,因为它在这里更方便,这给了我们:
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];
}
这不是实现目标的唯一方法。使用块和 Grand Central Dispatch(GCD)是另一种方法,在这种情况下,其优点是传递三个值:当前索引,限制和延迟;
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];
});
}
}
有关dispatch_X方法和方法的详细信息,请参见文档。
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。
这篇关于循环更改文本字段仅显示一个最终值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!