l.vasilev
l.vasilev

Reputation: 930

UI is not updating immediately after performing dispatch_async on main thead?

This is my code :

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
    for (int i = 0; i < size; i++)
    {

        CGRect frame;
        frame.origin.x = self.scrollView.frame.size.width * i;
        frame.size = self.scrollView.frame.size;

        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@%@x%@%@",
                                                        // some web service data

        UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageWithData:data]];

        UIView *subview = [[UIView alloc] initWithFrame:frame];

        imageView.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.bounds.size.width, self.view.bounds.size.height);
        [subview addSubview:imageView];
        [self.dataViewsArray addObject:subview];
        NSLog(@"dwonload bacgraound");

    }

    dispatch_async(dispatch_get_main_queue(), ^(void){
        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        NSLog(@"starting some UI updates");
        [self makeScrollPagingView];


    });
});

and [self makeScrollPagingView] - is just adding subview to my scrollview ? there is 10 seconds delay after my code is done . and then the ui is updated. Please help

Upvotes: 1

Views: 1488

Answers (2)

Kevin
Kevin

Reputation: 3131

A faster solution would be to not load your images concurrently, but in parallel:

for (int i = 0; i < size; i++) {
    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@""]]];
        CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data);
        CGImageRef imageRef = CGImageCreateWithPNGDataProvider(provider, NULL, false, kCGRenderingIntentDefault); // assuming PNG format, JPG is also available
        CGDataProviderRelease(provider);

        dispatch_async(dispatch_get_main_queue(), ^(void){
            UIImage *image = [UIImage imageWithCGImage:imageRef];
            CGImageRelease(imageRef);

            UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
            // Layout and position of just this UIImageView
        });
    });
}

but, depending on your uses, this might be a case a premature optimization at the expense of readability/simplicity. Create the UIImage on the main thread is probably good enough.

for (int i = 0; i < size; i++) {
    dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@""]]];

        dispatch_async(dispatch_get_main_queue(), ^(void){
            UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageWithData:data]];
            // Layout and position of just this UIImageView
        });
    });
}

Have you layout code not depend on having all the images loaded at once. And like Sashcha said, never do UI-related code in a background thread.

Some UIImageView libraries or categories might simplify the code you need to write. AFNetworking is a good one to start, it has UIImageView+AFNetworking that you should look at.

Upvotes: 3

This code is not tested, but shows, what I suggest:

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){

    NSMutableArray *images = [[NSMutableArray alloc] initWithCapacity:size];

    for (int i = 0; i < size; i++)
    {
        NSLog(@"Download in background");
        NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@%@x%@%@",
                                                    // some web service data

        [images addObject:data];
    }

    dispatch_async(dispatch_get_main_queue(), ^(void){
        for (int i = 0; i < size; i++)
        {
            CGRect frame;
            frame.origin.x = CGRectGetWidth(self.scrollView.frame) * i;
            frame.size = self.scrollView.frame.size;

            UIImage *image = [UIImage imageWithData:imageData];
            UIImageView *imageView = [[UIImageView alloc] initWithImage:image];

            UIView *subview = [[UIView alloc] initWithFrame:frame];

            imageView.frame = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.bounds.size.width, self.view.bounds.size.height);
            [subview addSubview:imageView];
            [self.dataViewsArray addObject:subview];
        }

        [images removeAllObjects];

        [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
        NSLog(@"starting some UI updates");
        [self makeScrollPagingView];


    });
});

Upvotes: 0

Related Questions