为什么即使在我的线程上查看也没有更新?

时间:2014-04-23 07:53:09

标签: ios objective-c objective-c-blocks

我试图意识到为什么在设置某个值时视图不会更新。问题看起来很简单,但我花了很多时间来找到问题 - 没有结果。

  • 当返回块中的最后一个值时,视图将更新为上次报告的进度值。
  • 滑块上的设置值在主线程上 - 在主线程上dispatch_async()执行更改后没有任何变化。

这是完整的代码:

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self performSelector:@selector(doUpdate) withObject:nil afterDelay:5.0f];
}


- (void)doUpdate {
    __weak typeof(self.slider) weakSlider = self.slider;
    [self doSomethingAndReportProgress:^(CGFloat progress) {
        NSLog(@"3. reported progress: %f", progress);
        weakSlider.value = progress; /// slider has range 0 - 100
        NSLog(@"4. weakSlider.value: %f", weakSlider.value);
    }];
}

- (void)doSomethingAndReportProgress:(void(^)(CGFloat))block {
    [self doSomethingOtherAndReportProgress:^(CGFloat progress) {
        block(progress);
        NSLog(@"2. reported progress: %f", progress);
    }];
}

- (void)doSomethingOtherAndReportProgress:(void(^)(CGFloat))block {
    for (int i = 0; i < 10000; i++) {
        CGFloat progress = i / 100.0;
        block(progress);
        NSLog(@"1. reported progress: %f", progress);
    }
}

@end

从控制台中删除日志:

2014-04-23 09:48:03.991 UIUpdateInBlock[87087:60b] 3. reported progress: 2.050000
2014-04-23 09:48:03.991 UIUpdateInBlock[87087:60b] 4. weakSlider.value: 2.050000
2014-04-23 09:48:03.991 UIUpdateInBlock[87087:60b] 2. reported progress: 2.050000
2014-04-23 09:48:03.992 UIUpdateInBlock[87087:60b] 1. reported progress: 2.050000
....
2014-04-23 09:48:04.421 UIUpdateInBlock[87087:60b] 3. reported progress: 3.950000
2014-04-23 09:48:04.422 UIUpdateInBlock[87087:60b] 4. weakSlider.value: 3.950000
2014-04-23 09:48:04.423 UIUpdateInBlock[87087:60b] 2. reported progress: 3.950000
2014-04-23 09:48:04.423 UIUpdateInBlock[87087:60b] 1. reported progress: 3.950000
....

为什么日志按顺序排列:3,4,2,1而不是1,2,3,4?

提前谢谢。

2 个答案:

答案 0 :(得分:2)

因为您在通话NSLog后放置了block(),只需将它们放在前面,您就会得到正确的结果;)

答案 1 :(得分:1)

这里有几件事

  1. 您在主线程上完成所有处理,阻止UI更新(这就是为什么您的滑块仅在循环结束时更新)。
  2. 您的日志显示与for语句中每个循环相反的顺序,在NSLog调用之前执行该块
  3. 要解决第一次使用dispatch_async以开始在后台运行循环(因此,不阻止UI线程)并在调用中执行滑块更新,如

    dispatch_async(dispatch_get_main_queue(), ^{
       // update slider
    });