【问题标题】:Updating UILabel in the middle of a for() loop在 for() 循环中间更新 UILabel
【发布时间】:2011-06-15 20:20:11
【问题描述】:

我有一个带有 for() 循环的方法。在那个循环中, mylabel.text 被更新了很多次。但是,实际的标签在方法完成之前不会在屏幕上更新,并使用 for() 循环中创建的最后一个值进行更新。

使用在 for() 循环中间更新的 NSLog,我看到标签的值确实发生了多次变化。

在 for() 循环中间不更新标签是 iOS 的一般做法吗?我想有办法做到这一点。

【问题讨论】:

标签: objective-c


【解决方案1】:

您可以通过告诉 run loop 像这样运行来更新 UI:

for (NSInteger i = 0; i < 10; i++) {
    [label setText:...];
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantPast]];
}

【讨论】:

  • 是的,运行循环已经在运行,但是告诉它像上面的例子一样运行将处理输入源,包括 UI 更新。
  • 确实非常漂亮的把戏。我不禁觉得操纵 runloop 有一些危险,但它确实有效,谢谢。
  • 请注意,这可能会产生各种奇怪的副作用。当你调用runMode:beforeDate: 时,各种事情都可能发生在你的循环中间。计时器可以触发; WebKit 可以做各种疯狂的事;延迟选择器可以触发。这是一个非常危险的伎俩。有时有用,偶尔需要(尤其是在 Mac 上),但不是通用工具。
  • 这太糟糕了;除非您真的知道自己在做什么,否则这不是一个好主意。 Rob 的回答要好得多。
【解决方案2】:

来自我之前的评论:

请注意,这 (runMode:beforeDate:) 可能会产生各种奇怪的副作用。当你调用 runMode:beforeDate: 时,各种事情都可能发生在你的循环中间。计时器可以触发; WebKit 可以做各种疯狂的事;延迟选择器可以触发。这是一个非常危险的伎俩。有时有用,偶尔需要(尤其是在 Mac 上),但不是通用工具。

更好的解决方案是在主调度队列上安排更新:

for (NSInteger i = 0; i < 10; i++) {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, i * NSEC_PER_SEC), 
                   dispatch_get_main_queue(), ^{
      [self.label setText:[NSString stringWithFormat:@"%d", i]];
    });
}

这会安排 10 次更新,间隔 1 秒。它可以适应各种其他需求,而无需在主运行循环上创建阻塞方法。

【讨论】:

  • 这非常有效。非常感谢。你是救生员!!
【解决方案3】:

试试

[yourLabel setNeedsDisplay];

【讨论】:

  • 不完全。 -setNeedsDisplay 安排在后续运行循环中更新视图——它不会立即触发重新绘制。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多