问题在于:我有一些像这样的代码
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中,文本每秒都会更改,只计为10。但是对于showMessage方法,文本为空整整十秒,然后只显示数字10.任何想法??FTR,showMessage方法就是
- (void)showMessage:(NSString *)text {
[[self message] setStringValue:text];
}
并不重要,这是非常基本的。
答案 0 :(得分:6)
如果明确地给运行循环一段时间运行,你可以在循环中实现所需的效果:
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow: 0.1]];
答案 1 :(得分: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;
}
}
答案 2 :(得分:1)
视图无法更新until the end of the run loop;你的for
循环不会让运行循环继续,所以你所做的所有视图更新都是在你的for循环退出后完成的。
您应该使用NSTimer
或performSelector: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的其余部分;你的用户将无法做任何事情,如果你睡得足够长,你就会得到旋转的沙滩球。
答案 3 :(得分: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;
}
}