我正在尝试使用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;
});
});