Question

I'm trying to realised why view isn't updating when some value is set. Problem looks as trivial one but I spent a lot of time to find the problem - with no results.

  • When last value from the block is returned view is updated to this last reported progress value.
  • setting value on slider is on main thread - nothing changes after execute change in dispatch_async() on main thread.

Here is whole code:

#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

Scrap of logs from console:

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
....

And why logs are in the order: 3, 4, 2 ,1 instead of 1, 2, 3, 4?

Thank you in advance.

Was it helpful?

Solution 2

Several things here

  1. All your processing is done on the main thread, blocking UI update (this is why your slider is only updated at the end of your loop).
  2. Your logs show a reverse order as for each loop in your for statement the block is executed before your NSLog call

To solve your 1st use a dispatch_async to start running your loop in the background (thus, not blocking your UI Thread) and do the slider update in a call like

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

OTHER TIPS

Because you put your NSLog after your call block(), just put them before and you will have the right result ;)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top