4

我想将我的应用程序中的进度条显示为确定的而不是不确定的。但是在将其设置为确定时它不起作用(对于不确定的工作就很好)。我已经阅读其他一些答案,尽管它们没有奏效。任何帮助将不胜感激 - 谢谢!

@interface AppDelegate : NSObject <NSApplicationDelegate> {

    IBOutlet NSProgressIndicator *showProgress;

}

- (IBAction)someMethod:(id)sender {

    [showProgress setUsesThreadedAnimation:YES];   // This works
    [showProgress startAnimation:self];            // This works
    [showProgress setDoubleValue:(0.1)];           // This does not work
    [showProgress setIndeterminate:NO];            // This does not work

    [self doSomething];
    [self doSomethingElse];
    [self doSomethingMore];
    ....

    [barProgress setDoubleValue:(1.0)];            // This does not work
    [barProgress stopAnimation:self];              // This works

}

更新的代码[工作]:

- (IBAction)someMethod:(id)sender {

    [showProgress setUsesThreadedAnimation:YES];
    [showProgress startAnimation:self];
    [showProgress setIndeterminate:NO];

    [showProgress setDoubleValue:(0.1)];
    [showProgress startAnimation:nil];

    dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(backgroundQueue, ^{

        for (NSUInteger i = 0; i < 1; i++) {

            dispatch_async(dispatch_get_main_queue(), ^{
                [barProgress incrementBy:10.0];
            });
        }

    [self doSomething];

            [showProgress incrementBy:...];

        dispatch_async(dispatch_get_main_queue(), ^{

            [showProgress stopAnimation:nil];

        });
    });

    [showProgress setDoubleValue:(1.0)];
}
4

1 回答 1

4

您的doSomething方法阻塞了主线程,这导致运行循环不循环,进而导致 UI 重绘被阻塞。解决方法是在doSomething后台队列中执行长时间运行的工作,并定期回调主队列以更新进度条。

我不知道你的doSomething方法是做什么的,但为了解释起见,我们假设它运行一个包含 100 步的 for 循环。你会像这样实现它:

- (void)doSomething
{
    [showProgress startAnimation:nil];
    dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(backgroundQueue, ^{
        for (NSUInteger i = 0; i < 100; i++) {
            // Do whatever it is you need to do

            dispatch_async(dispatch_get_main_queue(), ^{
                [showProgress incrementBy:1.0];
            });
        }
        // Done with long running task
        dispatch_async(dispatch_get_main_queue(), ^{
            [showProgress stopAnimation:nil];
        });
    });
}

请记住,您仍然需要将进度指示器设置为确定,初始化其值并设置适当的 minValue 和 maxValue。

如果您必须在doSomething主线程上完成工作,则可以安排在每个运行循环周期中完成该工作的一小部分,或者在您进行工作时定期手动旋转运行循环,但是 Grand Central Dispatch (GCD) 如果您可以使用它,那将是我的首选。

于 2012-06-04T23:19:08.967 回答