0

Webから画像をダウンロードする関数を作成しました。引数としてブロックを取ります。メモリキャッシュを追加するまで、すべてが正常に機能しました。画像がすでにキャッシュにある場合、関数は戻りません(ただし、ブロックはnilではありません)。

- (void) downloadImageFromURL:(NSURL *) url completionBlock:(void (^)(UIImage *image, NSError *error)) block {

dataHandler = [DataHandler sharedInstance];

UIImage *img=[dataHandler.avatarImages objectForKey:[url absoluteString]];
//image is in cache
if (img) {
    block(img, nil);
}
//not in cache, download it (works ok)
else {

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^{
        NSData *imageData = [NSData dataWithContentsOfURL:url];
        UIImage *picture=[UIImage imageWithData:imageData];
        if(picture) {
            //save to cache
            [dataHandler.avatarImages setObject:picture forKey:[url absoluteString]];
            block(picture, nil);
        }
        else {
            NSError *error = [NSError errorWithDomain:@"image_download_error" code:1
                                             userInfo:[NSDictionary dictionaryWithObject:@"Can't fetch data" forKey:NSLocalizedDescriptionKey]];
            block(nil, error);
        }

    });
}

ブロックは次のように呼び出されます。

        ImageDownloader *idl=[[ImageDownloader alloc] init];

        NSURL *imageUrl=[NSURL URLWithString:ta.avatarUrl];
        [idl downloadImageFromURL:imageUrl completionBlock:^(UIImage *image, NSError *error)
         {
             if(!error) {
                 dispatch_async(dispatch_get_main_queue(), ^(void) {
                     logo.image=image;
                 });
             } else {
                 NSLog(@"error %@", error);
             }

         }];
4

1 に答える 1

0

キャッシュ内の画像が次のようになったら、ブロックへの呼び出しを変更します。

if (img) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        block(img, nil);
    });
}

ユーザーは画像がキャッシュにあるかどうかを気にする必要はありません。いずれの場合も、ブロックは非同期と呼ばれる必要があります。

于 2012-10-26T13:47:49.963 に答える