Objective-C,如何显示确定的进度条?
Posted
技术标签:
【中文标题】Objective-C,如何显示确定的进度条?【英文标题】:Objective-C, how to display determinate progress bar? 【发布时间】:2012-06-04 23:04:46 【问题描述】:我想在我的应用程序中将进度条显示为确定的而不是不确定的。但是在将其设置为确定时它不起作用(对于不确定的工作就很好)。我有read some 的other 对此的回答,尽管它们没有奏效。任何帮助将不胜感激 - 谢谢!
@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)];
【问题讨论】:
【参考方案1】:您的doSomething
方法阻塞了主线程,导致run loop 不循环,进而导致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) 将是我的首选。
【讨论】:
——很棒的例子。我用您的代码示例更新了我的问题以反映工作版本;让我知道我是否遗漏任何内容或您发现任何问题。再次 ;-) 嗨——我有一个关于这个的快速问题。当进度条与启动动画的按钮相关联时,它工作正常。但是我不再需要按钮,即使使用[showProgress startAnimation:self];
等参数,动画也不再启动有什么想法吗?
你必须发布你的新代码让我给出任何建议。你又阻塞了主线程?我建议用你的新代码发布一个新问题。
不,代码一点也不新——它只是消除了 (IBAction) 而不是 void (这是您展示的方法)。我将其切换为 void,现在进度条不再显示(或进度)。有什么特别的东西我可能会错过吗?谢谢。您只能每 5 秒编辑一次评论。(单击此框可关闭)
IBAction 只是 void 的 #define(参见 AppKit/NSNibDeclarations.h),所以如果这真的是您所做的唯一更改,那么您编译的可执行文件将完全相同相同.如果不是通过按钮,您现在如何调用该方法?更改方法的调用方式很可能是新行为的原因。更改 IBAction -> void 本身没有任何意义。以上是关于Objective-C,如何显示确定的进度条?的主要内容,如果未能解决你的问题,请参考以下文章