iOS実戦:GCDを使用して複数の画像のダウンロード制御を実現
5002 ワード
開発中は、サブスレッドに時間がかかる操作がしばしば発生し、完了したらメインスレッドに戻ってUIを同期し、メインスレッドがブロックされないようにします.複数の時間のかかる操作を同時に処理し、すべての時間のかかる操作を処理した後にUIを同期する必要がある場合があります.この場合、GCDを使用できます.
需要1
同時に2枚の図をダウンロードする
同時に2枚の画像をダウンロードする必要があります.2枚の画像がダウンロードされた後、同時に戻ります.
グループを用いた概略実装
需要2
ダウンロードタイムアウト時間は2秒です
画像のダウンロードタイムアウト時間を2秒に設定し、画像が2秒後にすべてダウンロードされていない場合は、完了していない画像をnilで返します.
コード実装
注意waitは必ずサブスレッドに配置しなければなりません.そうしないと、メインスレッドがブロックされます.
具体的にGCDを使ってダウンロードを完了する際に発生した問題
問題1:非同期タスクが制御できない
光の上のコードは、実際には複数の画像のダウンロードの同期機能を実現することはできません.システムのパッケージされたダウンロードのクラスを使用すると、このようにしか使えないからです.
このコードを
では、どうすればいいですか.答えは
質問2:画像のダウンロードをキャンセルする方法
SDWebImageの
最後に、私のブログのアドレス:http://jabberyq.top/
需要1
同時に2枚の図をダウンロードする
同時に2枚の画像をダウンロードする必要があります.2枚の画像がダウンロードされた後、同時に戻ります.
グループを用いた概略実装
- (void)downloadImageSuccess:(void (^)(UIImage *image1, UIImage *image2))success {
dispatch_queue_t global_queue = dispatch_get_global_queue(0, 0);
dispatch_group_t group = dispatch_group_create();
__block UIImage *image1;
__block UIImage *image2;
dispatch_group_async(group, global_queue, ^{
NSLog(@" ");
sleep(2);
image1 = [UIImage new];
NSLog(@" ");
});
dispatch_group_async(group, global_queue, ^{
NSLog(@" ");
sleep(3);
image2 = [UIImage new];
NSLog(@" ");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@" ");
success(image1, image2);
});
}
需要2
ダウンロードタイムアウト時間は2秒です
画像のダウンロードタイムアウト時間を2秒に設定し、画像が2秒後にすべてダウンロードされていない場合は、完了していない画像をnilで返します.
コード実装
dispatch_group_wait
関数を使用します.- (void)downloadImageSuccess:(void (^)(UIImage *image1, UIImage *image2))success {
dispatch_queue_t global_queue = dispatch_get_global_queue(0, 0);
dispatch_group_t group = dispatch_group_create();
__block UIImage *image1;
__block UIImage *image2;
dispatch_group_async(group, global_queue, ^{
NSLog(@" ");
sleep(2);
image1 = [UIImage new];
NSLog(@" ");
});
dispatch_group_async(group, global_queue, ^{
NSLog(@" ");
sleep(4);
image2 = [UIImage new];
NSLog(@" ");
});
dispatch_async(global_queue, ^{
dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC));
dispatch_async(dispatch_get_main_queue(), ^{
success(image1, image2);
});
});
}
2018-12-09 21:56:15.007222+0800 GCDDemo[12279:450516]
2018-12-09 21:56:15.007222+0800 GCDDemo[12279:450524]
2018-12-09 21:56:17.011723+0800 GCDDemo[12279:450516]
2018-12-09 21:56:18.007809+0800 GCDDemo[12279:450477] , {0, 0} (null)
2018-12-09 21:56:19.008913+0800 GCDDemo[12279:450524]
注意waitは必ずサブスレッドに配置しなければなりません.そうしないと、メインスレッドがブロックされます.
具体的にGCDを使ってダウンロードを完了する際に発生した問題
問題1:非同期タスクが制御できない
光の上のコードは、実際には複数の画像のダウンロードの同期機能を実現することはできません.システムのパッケージされたダウンロードのクラスを使用すると、このようにしか使えないからです.
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:[NSURL URLWithString:@"image"] completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
}];
[task resume];
このコードを
dispatch_group_async
に直接投げ込むと、非同期でタスクのダウンロードを開始するしかなく、タスクを同期する機能はできません.次のようになります. dispatch_group_async(group, global_queue, ^{
dispatch_sync(con_queue, ^{
// TODO
});
});
では、どうすればいいですか.答えは
dispatch_group_enter
とdispatch_group_leave
の方法を使用します.具体的なシミュレーションの使用: dispatch_queue_t global_queue = dispatch_get_global_queue(0, 0);
dispatch_group_t group = dispatch_group_create();
__block UIImage *image1;
__block UIImage *image2;
dispatch_group_enter(group);
dispatch_group_async(group, global_queue, ^{
dispatch_sync(con_queue), ^{
NSLog(@" ");
sleep(2);
image1 = [UIImage new];
NSLog(@" ");
dispatch_group_leave(group);
});
});
dispatch_group_enter(group);
dispatch_group_async(group, global_queue, ^{
dispatch_sync(con_queue), ^{
NSLog(@" ");
sleep(4);
image2 = [UIImage new];
NSLog(@" ");
dispatch_group_leave(group);
});
});
dispatch_async(global_queue, ^{
dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC));
dispatch_async(dispatch_get_main_queue(), ^{
success(image1, image2);
});
});
2018-12-09 22:23:36.918395+0800 GCDDemo[12558:492481]
2018-12-09 22:23:36.918395+0800 GCDDemo[12558:492483]
2018-12-09 22:23:38.923074+0800 GCDDemo[12558:492481]
2018-12-09 22:23:39.919640+0800 GCDDemo[12558:492349] , {0, 0} (null)
2018-12-09 22:23:40.923513+0800 GCDDemo[12558:492483]
質問2:画像のダウンロードをキャンセルする方法
SDWebImageの
SDWebImageDownloader
クラスを使用すると、ダウンロードを直接キャンセルできます.またNSURLSessionDownloadTask
クラスにもcancelメソッドがあるのを見ましたが、試してみませんでした..最後に、私のブログのアドレス:http://jabberyq.top/