2011-04-29 50 views
2

这里的问题:我有一些代码,是这样的的NSTextField等待,直到一个循环结束更新

otherWinController = [[NotificationWindowController alloc] init]; 
for (int i = 0; i < 10; i++) { 
    [otherWinController showMessage:[NSString stringWithFormat:@"%d", i]]; 
    NSLog(@"%d", i); 
    sleep(1); 
} 

其中otherWinController是NSWindowController的一个子类,我现在用的改变发生在更新我的窗口在代码中,alloc init方法只是打开了nib并显示了窗口。 showMessage是一种更改NSTextView以显示参数中的任何文本的方法。

在NSLog中,文本每秒都在变化,只是数到十。然而,对于showMessage方法,文本在整整十秒内是空白的,然后只显示数字10.任何想法?

FTR中,showMessage方法很简单

- (void)showMessage:(NSString *)text { 
[[self message] setStringValue:text]; 
} 

不是它应该的问题,这是非常基本的。

回答

0

我认为通过调用sleep(1)你可以阻塞主线程,它必须绘制你的改变。所以显示不会更新。任务管理器不会中断你的功能。在这种情况下,您不应该使用sleep。请看NSTimer班。它有一个静态方法scheduledTimerWithTimeInterval,你应该使用它。

static UIViewController *controller = nil; 
..... 
{ 
..... 
otherWinController = [[NotificationWindowController alloc] init]; 
controller = otherWinController; 
[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timerTick:) userInfo:nil repeats:YES]; //set timer with one second interval 
..... 
} 

- (void) timerTick:(NSTimer*)theTimer { 
    static int i = 0; 
    [controller showMessage:[NSString stringWithFormat:@"%d", i]]; 
    NSLog(@"%d", i); 
    if (++i == 10) { 
     [theTimer invalidate]; 
     i = 0; 
    } 
} 
2

的问题是,您阻止主线程你for循环和用户界面更新发生在主线程。包含for循环的方法执行完毕后,主线程运行循环将只会旋转(因此用户界面更新将发生)。

如果您想每秒更新一次该文本字段,则应使用计时器。例如,考虑otherWinController是一个实例变量,在你的类声明counter财产:

otherWinController = [[NotificationWindowController alloc] init]; 
self.counter = 0; 
[otherWinController showMessage:[NSString stringWithFormat:@"%d", self.counter]]; 

[NSTimer scheduledTimerWithTimeInterval:1.0 
           target:self 
           selector:@selector(updateCounter:) 
           userInfo:nil 
           repeats:YES]; 

在同一个类中,实现的是被称为每当时间已被解雇的方法:

- (void)updateCounter:(NSTimer *)timer { 
    self.counter = self.counter + 1; 
    [otherWinController showMessage:[NSString stringWithFormat:@"%d", self.counter]]; 

    if (self.counter == 9) { 
     [timer invalidate]; 
     // if you want to reset the counter, 
     // self.counter = 0; 
    } 
} 
1

视图不会更新until the end of the run loop;您的for循环不会让运行循环继续,因此您所做的所有视图更新都是在for循环退出后完成的。

您应该使用NSTimerperformSelector:withObject:afterDelay:以循环方式更改显示。

[NSTimer scheduledTimerWithTimeInterval:1 
           target:self 
           selector:@selector(changeTextFieldsString:) 
           userInfo:nil 
           repeats:YES]; 

然后你的计时器的动作会改变看法的形象:

- (void)changeTextFieldsString:(NSTimer *)tim { 
    // currStringIdx is an ivar keeping track of our position 
    if(currStringIdx >= maxStringIdx){ 
     [tim invalidate]; 
     return; 
    } 
    [otherWinController showMessage:[NSString stringWithFormat:@"%d", currStringIdx]] 
    currStringIdx++; 
} 

也一般不希望使用sleep除非你在后台线程,因为它会锁定剩下的的UI;你的用户将无法做任何事情,如果你睡得足够长,你会得到旋转的沙滩球。

6

你或许可以达到预期的效果就在您的内循环,如果你明确给出的运行循环一段时间运行:

[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow: 0.1]]; 
+0

怪异,但它确实工作。 – 2011-04-29 09:39:29

+0

在桌面上执行此操作时很常见,在等待异步过程完成时运行(模态)UI。 – 2011-04-29 10:02:56

+0

有道理;感谢您分享提示! – 2011-04-29 18:11:29

相关问题