如何在没有线程的循环中更新iOS中的UI元素?

时间:2011-06-12 18:23:06

标签: iphone ios uiview

我想从循环中更新标签,例如:

- (void)viewDidLoad {
    [super viewDidLoad];
    int i=0; 
    while (1) {
         i++;
         [NSThread sleepForTimeInterval:0.05];  // do some computation,
         [myLabel setText:[NSString stringWithFormat:@"%d", i]]; // show the result!
         [self.view setNeedsDisplay];
    }

  }

假设不进行睡眠而是进行一些繁重的计算。 我不想在后台进行计算的开销。 用于处理此问题的Windows等效项将是.DoEvents,如此示例所示: http://www.tek-tips.com/viewthread.cfm?qid=1305106&page=1

在iOS中是否有类似的解决方案?

[self.view setNeedsDisplay]根本不起作用!

必须有一些方法可以在主线程中以受控的时间表从iOS处理应用程序事件...就像Windows中的.DoEvents一样,尽管它的所有缺点对于一些简单的应用程序非常有用。

我想这就像游戏循环,但有UI组件。

5 个答案:

答案 0 :(得分:3)

您这样做的方式如下:

-(void) incrementCounter:(NSNumber *)i {             
    [myLabel setText:[NSString stringWithFormat:@"%d", [i intValue]]]; // show the result!
    [self performSelector:@selector(incrementCounter:) withObject:[NSNumber numberWithInt:i.intValue+1] afterDelay:0.05];    
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // start the loop
    [self incrementCounter:[NSNumber numberWithInt:0]];
}

这里的基本思想是在稍微延迟0.05之后递增计数器,以使主UI线程有机会刷新所有UI事件,这构成了在Windows世界中显式调用.DoEvents。

答案 1 :(得分:1)

我假设你想用标签实现一个计数器?例如,您可以使用NSTimer来调用每隔X毫秒更新计数器的方法。

答案 2 :(得分:1)

如果要更新UI组件,请在NSTimer中使用iOS

NSTimer* myTimer = [NSTimer scheduledTimerWithTimeInterval: 60.0 target: self
                                   selector: @selector(callAfterSomeSecond:) userInfo: nil repeats: YES];

实施callAfterSomeSecond:如下所示:

-(void) callAfterSomeSecond:(NSTimer*) timer 
{
   static int counter = 0;

   if(counter == 100)
   {
      [timer invalidate];
   }
   [myLabel setText:[NSString stringWithFormat:@"%d", counter ]];
   [self.view layoutSubviews];
   counter++;
}

答案 3 :(得分:0)

在你的代码中,while循环在主线程中运行,UI更新也应该在主线程中完成,所以当循环运行时,主线程有点'阻塞'(忙),所以UI无法执行更新。

我想我想说的不是你想要的。要解决它,你必须使用NSOperation或GCD将重计算放在另一个线程中。

答案 4 :(得分:0)

最好的方法是在不同的线程上进行计算,但是如果不可行,可以将影响UI的代码包装在CATransaction中。在我的测试中,这将立即更新UI,而无需等到下一个运行循环。

while (1) {
 [CATransaction begin];
 //Your UI code here
 [CATransaction commit];
}