2016-11-21 12 views
2

私は多くのURLリンクを含むarrayOfLinksを持っています。私はこれらのリンクから画像を取得する必要があります。私はそうするために次のコードを使用しています。目的C:画像が完成する前にループが終了しました

- (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

を、あるいは? –

+0

がすべて完了したら申し訳ありませんが、私はそれを明確にするためにそれを編集することを確認します。 – Weakman10122

答えて

2

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使用することができます。それらの_all_が行われた後、最後に一度だけ_each_後

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

EDIT:__block属性はブロックを作る

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

:この答えは、コメントでジョシュが指摘したように、私はindex == totalチェック

との競合状態がこれを試してみてください見ることができなかった、悪いです変数へのポインタを使用して、ブロックの実行間で値を変更できるようにします。それで、インデックス変数を増やす方法です。 total__blockではないので、ブロックを定義するときの現在の状態はtotalで、ブロックが実行されるたびに使用されます。したがって、ブロック内のtotal100から10に設定しても、次回のブロック実行時にはtotal10と表示されます。

+1

ここでは競合条件があります。複数のインクリメントが対応する比較の前に実行される場合、 'finishSettingImages'は複数回実行できます。 –

+0

ああ、うれしいよ。私は '__block'を使って答えを諦めた –

関連する問題