我正在尝试使用GCD块将图像从远程位置存储到NSMutableArray。以下代码在viewDidLoad中被调用,图像将被填充到UICollectionView中:

dispatch_apply(self.count, dispatch_get_global_queue(0, 0), ^(size_t i){

    NSString *strURL = [NSString stringWithFormat:@"%@%zu%@", @"http://theURL.com/popular/", i, @".jpg"];
    NSURL *imageURL = [NSURL URLWithString:strURL];
    NSData *imageData = [NSData dataWithContentsOfURL: imageURL];
    UIImage *oneImage =[UIImage imageWithData:imageData];
    if(oneImage!=nil){
        [self.imageArray addObject:oneImage];
    }

    });
PROBLEM:图像不是线性存储的。
例如。
[self.imageArray objectAtIndex:2]不是2.jpg即使正确设置了第一张和最后一张图像,其他所有内容都被弄乱了。

另一种方法(我基本上需要的是减去消耗的时间和内存开销):
for (int i=0; i<=[TMAPopularImageManager sharedInstance].numberOfImages-1; i++){

        NSString *strURL = [NSString stringWithFormat:@"%@%d%@", @"http://theURL.com/popular/", i, @".jpg"];
    NSURL *imageURL = [NSURL URLWithString:strURL];
    NSData *imageData = [NSData dataWithContentsOfURL: imageURL];
    UIImage *oneImage =[UIImage imageWithData:imageData];
    if(oneImage!=nil){
        [self.imageArray addObject:oneImage];
    }

}

在这种情况下,有没有更好的方法来实现GCD模块?我需要按顺序命名数组中的图像。

最佳答案

我运行了大约10次,但没有按顺序打印一次:

NSInteger iterations = 10;
dispatch_apply(iterations, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long) NULL), ^(size_t index) {
    NSLog(@"%zu", index);
});

我的建议以及我过去所做的就是在后台线程的块内运行一个for循环:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long) NULL);
dispatch_async(queue, ^{
    int iterations = 0;
    for (int x = 0; x < iterations; ++x) {
        // Do stuff here
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        // Set content generated on background thread to main thread
    });
});

使用后台线程时,重要的是要确保在主线程上初始化的对象是线程安全的,或者在后台初始化对象,然后使用由后台线程创建的对象设置主线程的对象,例如在上面的示例中。对于核心数据尤其如此。

编辑:

似乎使用dispatch_apply的迭代会立即返回,因此在进行有意义的操作时它们可能会无序执行。如果运行这两个,您将看到printf始终按顺序运行,但NSLog却没有:
NSInteger iterations = 10;
dispatch_apply(iterations, the_queue, ^(size_t idx) {
    printf("%zu\n", idx);
});

dispatch_apply(iterations, the_queue, ^(size_t idx) {
    NSLog(@"%zu\n", idx);
});

我认为,如果顺序很重要,最好在后台线程中运行语句标准,而不要使用dispatch_apply。

编辑2:

这将是您的实现:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, (unsigned long) NULL);
dispatch_async(queue, ^{
    int iterations = 0;
    NSMutableArray *backgroundThreadImages = [NSMutableArray array];
    for (int i = 0; i < iterations; ++i) {
        NSString *strURL = [NSString stringWithFormat:@"%@%i%@", @"http://theURL.com/popular/", i, @".jpg"];
        NSURL *imageURL = [NSURL URLWithString:strURL];
        NSData *imageData = [NSData dataWithContentsOfURL: imageURL];
        UIImage *oneImage =[UIImage imageWithData:imageData];
        if(oneImage!=nil){
            [backgroundThreadImages addObject:oneImage];
        }
    }
    dispatch_async(dispatch_get_main_queue(), ^{
        self.imageArray = backgroundThreadImages;
    });
});

07-24 09:44
查看更多