0

我有一个 IBAction,里面有一些简单的代码:

-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    [self dolengthyaction];
}

'textfield' 是 nib 文件中的 NSTextField,而 -'dolengthyaction' 是一个需要大约一分钟才能完成执行的函数。

我的问题是:为什么在执行“dolongyaction”之后才显示文本字段?我希望它在 dolongyaction 开始发生之前被揭露。这是一个固有问题还是我的代码有问题?(或在我的代码的另一部分?)

我仍然不是很擅长编程,所以如果我措辞不好并且格式错误,我深表歉意。

编辑:除了这个 IBAction 和 -dolongyaction 没有什么别的了...

-(void)doLengthyAction {
    sleep(10);
}
-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    [self doLengthyAction];
    [textfield setHidden:YES];
}

我真正想做的就是在动作运行时显示标签,并在动作完成时隐藏它。

基本上这意味着它现在根本没有显示。

实际上,在 -doLengthyAction 中,它不是 sleep(10),而是一个 NSFileManager 操作,它复制了大约 50 Mb 的材料。代码相当长,但如果你想让我发布它,我可以。我用 sleep() 对其进行了测试,但它也不起作用。

4

6 回答 6

6

所有绘图操作(包括隐藏和显示视图)都是从运行循环触发的。在您的函数返回之前,运行循环无法执行下一个事件。

如果您有一个运行时间超过一秒的操作,您应该在一个线程中执行它。完成后,使用 performSelectorOnMainThread 在主线程上进行 UI 更改。

于 2010-05-04T02:00:42.790 回答
5

正如前面一些答案中提到的,应用程序必须在重绘之前返回到主运行循环(这是一种优化,可以避免在进行许多更改时重绘)。

如果它们要运行很长时间,你真的应该在后台线程上处理它们。如果您不这样做,则 UI 将在您的操作运行时进行沙滩球。

如果你的目标是 10.6+,你可以使用 GCD 和如下块在后台轻松运行(并且不必定义多个方法来完成工作):

-(void)doLengthyAction {
    sleep(10);
}
-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [self doLengthyAction];
        dispatch_async(dispatch_get_main_queue(), ^{
            [textfield setHidden:YES];
        });
    });
}

当然,通过使用它,您需要确保在冗长的操作中发生的事情是线程安全的,但您最终会获得更好的用户体验。有关此类 CGD 代码的更多信息,您可能需要阅读此内容

于 2010-05-04T02:24:23.637 回答
1

我认为您的其余代码有问题。这不应该发生。

多发帖?

于 2010-05-04T01:00:36.353 回答
1

如果不查看其余代码,就无法说出到底发生了什么,但一种骇人听闻的方法是尝试:

-(IBAction)change:(id)sender {
   [textfield setHidden:NO];
   [self performSelector:@selector(doLenghtyAction) withObject:nil afterDelay:0.1]; --> or maybe even 0.0
 }
于 2010-05-04T01:13:22.817 回答
1
-(void)doLengthyAction {
     sleep(10);
    [textfield setHidden:YES];
} 

-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(doLengthyAction) userInfo:nil repeats:NO];
}
于 2010-05-04T01:46:06.823 回答
0

试试这个:

-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    [[textfield window] display]; // force the window to update
    [self doLengthyAction];
    [textfield setHidden:YES];
}
于 2010-05-04T03:38:26.580 回答