Tomasz Szulc
Tomasz Szulc

Reputation: 4235

Why view isn't updating even on my thread?

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.

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.

Upvotes: 1

Views: 92

Answers (2)

Eric Genet
Eric Genet

Reputation: 1260

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
});

Upvotes: 1

Tancrede Chazallet
Tancrede Chazallet

Reputation: 7245

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

Upvotes: 2

Related Questions