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

问题描述:

我想更新从一个循环的标签,例如像这样:iOS中的UI元素如何从没有线程的循环中更新?

- (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组件。

+0

尝试使用performSelector:withObject:afterDelay: http://developer.apple.com/library/ios/#DOCUMENTATION/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/instm/NSObject/performSelector:withObject:afterDelay:inModes: – AmineG 2011-06-12 18:25:53

+0

[self.view performSelector:@selector(setNeedsDisplay)withObject:nil afterDelay:0];不工作... – brbr 2011-06-12 18:45:03

+0

[self performSelectorOnMainThread:@selector(heavyDutyComputation)withObject:nil waitUntilDone:YES];不起作用... – brbr 2011-06-13 06:46:07

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

+0

这没有帮助!请阅读! – brbr 2011-06-12 18:42:10

使用NSTimeriOS如果你想更新UI组件。

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++; 
} 
+0

定时器是没有选择的(因为循环可能永远不会退出,我们想修改该循环内的用户界面)。如果主线程被阻塞,我认为计时器不会工作。 – brbr 2011-06-12 18:51:11

+0

@brbr:当'counter'变为100时它将退出。看到我在100处使'NSTimer'无效。 – Jhaliya 2011-06-12 18:52:46

在你的代码

,while循环在主线程中运行,而UI更新也应该在主线程中完成,因此而循环正在运行,主线程是'阻塞'(繁忙),所以UI更新无法执行。

我想我想说的是不是你想要的。为了解决这个问题,你必须将重载计算放在另一个线程中,例如使用NSOperation或GCD。

你会做到这一点的方法如下:

-(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。