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

发布于 2024-08-31 01:24:26 字数 814 浏览 5 评论 0原文

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

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

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

我的问题是:为什么在“dolengthyaction”执行完成之后才显示文本字段?我希望在漫长的行动开始之前将其揭晓。这是一个固有的问题还是我的代码有问题? (或者在我代码的另一部分?)

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

编辑:除了这个 IBAction 和 -dolengthyaction 之外没有太多其他的...

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

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

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

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

I have an IBAction with some simple code inside:

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

'textfield' is an NSTextField in a nib file, and -'dolengthyaction' is a function that takes about a minute to finish executing.

My question is: Why isn't the textfield shown until AFTER "dolengthyaction" is done executing? I want it to be revealed before the dolengthyaction starts taking place. Is this an inherent problem or is there something wrong with my code? (or in another part of my code?)

I'm still not very good at programming so I apologize if I worded something badly and formatted something wrong.

EDIT: There isn't much else other than this IBAction and -dolengthyaction...

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

All I really want to do is display the label when the action is running and hide it when it's done.

Basically what this means is that it's not displaying at all right now.

In reality, in -doLengthyAction it's not sleep(10) but rather a NSFileManager operation that copies about 50 Mb of material. The code was rather long, but if you want me to post it I can. I tested it with sleep() but it doesn't work either.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

风筝在阴天搁浅。 2024-09-07 01:24:26

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

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

All drawing operations (including hiding and showing views) are triggered from the run loop. The run loop cannot perform the next event until after your function returns.

If you have an operation that takes more than a second to run, you should perform it in a thread. Once it completes, use performSelectorOnMainThread to make UI changes on the main thread.

为你拒绝所有暧昧 2024-09-07 01:24:26

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

如果它们要运行很长时间,您确实应该在后台线程上处理它们。如果不这样做,用户界面将在您的操作运行时崩溃。

如果您的目标是 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 代码的更多信息,您可能需要 阅读此内容

As mentioned in some of the previous answers, the application must return to the main run loop before it will redraw (it's an optimization to avoid redrawing when you make many changes).

You really should handle things on a background thread if they're going to run for a long time. If you don't the UI will beach ball while your operation runs.

If you're targeting 10.6+, you can use GCD and blocks as follows to run things easily in the background (and not have to define multiple methods to get things done):

-(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];
        });
    });
}

Of course by using this, you'll need to make sure that what's going on in the lengthy action is thread safe, but you'll end up with a better user experience. For more info on this type of CGD code, you might want to read this.

独孤求败 2024-09-07 01:24:26

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

多发帖?

I think there is something wrong with the rest of your code. This should not happen.

Post more?

小…红帽 2024-09-07 01:24:26

如果不查看其余代码,无法说出到底发生了什么,但一种黑客方法是尝试:

-(IBAction)change:(id)sender {
   [textfield setHidden:NO];
   [self performSelector:@selector(doLenghtyAction) withObject:nil afterDelay:0.1]; --> or maybe even 0.0
 }

Can't say what exactly is transpiring with out looking at rest of the code, but a hackish way would be to try:

-(IBAction)change:(id)sender {
   [textfield setHidden:NO];
   [self performSelector:@selector(doLenghtyAction) withObject:nil afterDelay:0.1]; --> or maybe even 0.0
 }
苏别ゝ 2024-09-07 01:24:26
-(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];
}
-(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];
}
全部不再 2024-09-07 01:24:26

试试这个:

-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    [[textfield window] display]; // force the window to update
    [self doLengthyAction];
    [textfield setHidden:YES];
}

Try this:

-(IBAction)change:(id)sender {
    [textfield setHidden:NO];
    [[textfield window] display]; // force the window to update
    [self doLengthyAction];
    [textfield setHidden:YES];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文