在主线程上执行dispatch_async后,UI没有立即更新?

时间:2014-03-04 22:06:31

标签: ios grand-central-dispatch

这是我的代码:

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];


    });
});

[self makeScrollPagingView] - 只是将子视图添加到我的滚动视图中? 我的代码完成后有10秒的延迟。然后更新ui。请帮忙

2 个答案:

答案 0 :(得分:3)

更快的解决方案是不同时加载图像,而是并行加载:

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

但是,根据您的使用情况,这可能是以可读性/简单性为代价的过早优化。在主线程上创建UIImage可能已经足够了。

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

布局代码是否依赖于一次加载所有图像。和Sashcha说的一样,永远不要在后台线程中使用与UI相关的代码。

某些UIImageView库或类别可能会简化您需要编写的代码。 AFNetworking是一个很好的开始,你应该看UIImageView+AFNetworking

答案 1 :(得分:0)

此代码未经过测试,但显示了我的建议:

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];


    });
});