UIProgressBar 没有循环更新

Posted

技术标签:

【中文标题】UIProgressBar 没有循环更新【英文标题】:UIProgressBar isn't updated in loop 【发布时间】:2014-01-29 15:54:57 【问题描述】:

以前有人问过这个问题,但答案不起作用。我知道(如果我错了,请纠正我)主线程更新 UI,所以我们需要在循环中调用主线程。我正在尝试这个,进度条只在循环结束时更新(所以从 0% 到 100%)

这是我的代码

.h

@interface ViewController : UIViewController <UITextFieldDelegate> 
IBOutlet UIProgressView *progressBar;
float progressBarPercentage;

-(IBAction)button:(id)sender;

@end

.m

-(IBAction)button:(id)sender

for (int z=0; z < 9; z++)

//do stuff

float progressBarPercentage = (1.0 / 9.0 * (z + 1));
        [self performSelectorOnMainThread:@selector(makeMyProgressBarMove) withObject:nil waitUntilDone:NO];





-(void)makeMyProgressBarMove

    [progressBar setProgress:progressBarPercentage animated:YES];
     

在调试模式下运行时,我注意到当它到达[self performSelectorOnMainThread:@selector(makeMyProgressBarMove) withObject:nil waitUntilDone:NO]; 行时,它只是重新启动循环而不转到 1makeMyProgressBarMove:`

另外,//do stuff 部分并不短,按下按钮时运行代码实际上需要 5 秒,所以它不像它更新的那么快我看不到它。

谢谢,如果需要更多信息,请告诉我,我还是个初学者

【问题讨论】:

你还需要在另一个线程上“做东西”,否则它仍然会阻塞你的主线程。请注意,如果您已经在主线程上,performSelectorOnMainThread 将毫无用处。 我在 ViewController.m 上,那是主线程吗? progressBarPercentage 是在 IBAction 内部还是外部声明? 我忘了添加,我会编辑,但它在我的 .h 文件中声明为浮点数 是否在主线程上与您所在的文件或您的方法在哪个对象上运行无关,而与方法的调用方式有关。在这里,您的方法在主线程上运行,因为它是从 UI 中的按钮调用的(与 UI 相关的所有操作都始终在主线程上完成)。 【参考方案1】:

你还需要在另一个线程上“做东西”,否则它仍然会阻塞你的主线程。请注意,如果您已经在主线程上,performSelectorOnMainThread 将毫无用处。

使用 libdispatch 因为它更容易:

-(IBAction)button:(id)sender
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
        for (int z=0; z < 9; z++)
        
            //do stuff

            float progressBarPercentage = (1.0 / 9.0 * (z + 1));

            dispatch_async(dispatch_get_main_queue(), ^
                [progressBar setProgress:progressBarPercentage animated:YES];
            );
        
    );

【讨论】:

是的,对不起。这应该是固定的! 好的,它可以工作了......你能解释一下为什么吗? dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) 是什么东西? 队列是线程的抽象,使它们更容易使用 IMO。将它们视为能够以 FIFO 顺序执行任意代码块的东西。 dispatch_async 是一个将块提交到队列执行并立即返回的函数。因此,您的 button: 方法返回并且不会阻塞您的主线程。与此同时,发送到(第一个)dispatch_async 的块开始执行,并周期性地用另一个 dispatch_async 回调主线程来更新你的进度条。 如果你想更深入地理解为什么阻塞主线程是一个问题以及调度队列如何解决这个问题,你应该阅读运行循环(一个非常重要的概念)、线程和调度队列.我敢肯定有很多文章比我能用更清晰的术语解释它:) 非常感谢!我会阅读更多。我不在任何与计算机相关的领域,所以所有的概念对我来说都是很新的!再次感谢塔姆! :D【参考方案2】:

现在试试这个

 -(IBAction)button:(id)sender

    for (int z=0; z < 9; z++)

    //do stuff

    float progressBarPercentage = (1.0 / 9.0 * (z + 1));
            [self performSelectorOnMainThread:@selector(makeMyProgressBarMove) withObject:nil waitUntilDone:YES];

    

    

    -(void)makeMyProgressBarMove

        [progressBar setProgress:progressBarPercentage animated:YES];
         

【讨论】:

我刚刚检查了调试器,它正在移动到makeMyProgreeBarMove: 方法,但它仍然没有更新进度条

以上是关于UIProgressBar 没有循环更新的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式快速制作 UIProgressBar

将 UIProgressBar 放在 UIToolbar 上

UIProgressBar:如何根据背景颜色更改 UILabel 颜色

IOS:多个 NSUrlConnection 以及多个 UIProgressBar

Xamarin。 WebView Progres

JavaScript。在循环执行期间没有更新带有 innerHTML 的循环