在Cocoa中,为什么在IBAction完全执行之后才会显示文本字段?

Ver*_*ous 0 cocoa objective-c interface-builder nib ibaction

我有一个内部有一些简单代码的IBAction:

-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    [self dolengthyaction];
}
Run Code Online (Sandbox Code Playgroud)

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

我的问题是:为什么在"dolengthyaction"执行完之后才显示文本字段?我希望在dolengthyaction开始之前揭示它.这是一个固有的问题还是我的代码有问题?(或在我的代码的另一部分?)

我仍然不擅长编程,所以如果我措辞严厉并且格式错误,我会道歉.

编辑:除了这个IBAction和-dolengthyaction之外别无其他......

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

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

基本上这意味着它现在还没有显示出来.

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

dra*_*ard 6

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

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


wby*_*ung 5

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

如果他们要运行很长时间,你真的应该在后台线程上处理事情.如果你不这样做,那么在你的操作运行时,用户界面就会起球.

如果你的目标是10.6+,你可以使用GCD和block如下在后台轻松运行(而不必定义多种方法来完成任务):

-(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];
        });
    });
}
Run Code Online (Sandbox Code Playgroud)

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