我有一个包含很多网址链接的arrayOfLinks
。我需要从这些链接获取图像。我使用以下代码来执行此操作。
- (void)getImages {
NSArray *links = arrayOfLinks;
for (NSString *link in links ) {
[self.picImage sd_setImageWithURL:[NSURL URLWithString:link] placeholderImage:nil options:SDWebImageHighPriority completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
NSLog(@"pic image set finished");
}];
}
[self finishSettingImages];
NSLog(@"for loop finished");
}
这几乎可以工作,但问题是在设置图像之前for循环完成。我想在设置每个图像后调用方法finishSettingImages
。最好的方法是什么?
编辑:我希望在设置所有图像后调用方法'finishSettingImages'。很抱歉没有澄清这一点。
答案 0 :(得分:3)
只需使用GCD组。
NSArray *links = arrayOfLinks;
dispatch_group_t group = dispatch_group_create();
for (NSString *link in links) {
dispatch_group_enter(group);
[self.picImage sd_setImageWithURL:[NSURL URLWithString:link] placeholderImage:nil options:SDWebImageHighPriority completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
dispatch_group_leave(group);
}];
}
// you can use dispatch_get_main_queue() or background here
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// all is done
});
如果您只需要获取图像,可以使用SDWebImageManager:
NSArray *links = arrayOfLinks;
__block NSMutableArray *images = [NSMutableArray new];
dispatch_group_t group = dispatch_group_create();
for (NSString *link in links) {
dispatch_group_enter(group);
SDWebImageManager *manager = [SDWebImageManager sharedManager];
[manager downloadImageWithURL:[NSURL URLWithString:link]
options:SDWebImageRetryFailed
progress:^(NSInteger receivedSize, NSInteger expectedSize) {}
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
if (image) {
[images addObject:image];
}
dispatch_group_leave(group);
}];
}
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
// all is done
for (UIImage *image in images) {
//do something with images
}
});
Swift 3/4的代码示例:
var arrayOfLinks = ... // you string links are here
let dispatchGroup = DispatchGroup()
for link in arrayOfLinks {
if let url = URL(string: link) {
dispatchGroup.enter()
self.imageView.sd_setImage(with: url) { (image, error, cacheType, url) in
dispatchGroup.leave()
}
}
}
dispatchGroup.notify(queue: .main) {
print("all is done ")
}
答案 1 :(得分:0)
index == total
支票的竞争条件
试试这个:
- (void)getImages
{
NSArray *links = arrayOfLinks;
NSUInteger total = [links count];
__block NSUInteger index = 0;
__weak id *weakSelf = self; //if your picImage retains the completion block as a property,
//then you will want to capture a weak reference to self, so you don't have a retain cycle
for (NSString *link in links ) {
[self.picImage sd_setImageWithURL:[NSURL URLWithString:link] placeholderImage:nil options:SDWebImageHighPriority completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
NSLog(@"pic image set finished");
index += 1;
if( index == total )
{
//again if you don't store this block as a property, you can just reference self instead of weakSelf
[weakSelf finishSettingImages];
}
}];
}
NSLog(@"for loop finished");
}
__block
属性使块使用指向变量的指针,以便它可以修改块执行的值。这就是我们如何增加索引变量的方法。 total
不是__block
所以当您定义块时total
的当前状态是每次块执行时将使用的内容。因此,即使您在块中total
设置100
到10
,下次块执行时仍会看到total
为10
。