需要返回值的异步图像下载

Posted

技术标签:

【中文标题】需要返回值的异步图像下载【英文标题】:Asynchrone image download with return value required 【发布时间】:2014-06-05 08:40:20 【问题描述】:

我正在尝试在我的应用程序上设置图像的异步下载。 我按照this issue 中的建议使用SDWebImage。

我在progresscompleted方法上设置了断点,一切正常。它运行良好,但我的逻辑直接产生了另一个问题。我不知道如何在我的UIImageView 上异步设置我的图像。 一切都是动态的,每个图像都是独立调用的

这是我的代码的一部分:

 [myMenu->_userAvatar setImage:[[CacheCache sharedInstance] getUIImageFromPath:currentUser.avatarPhoto.avatarURL]]; 

注意CacheCache是我自己的缓存方法。

NSURL* myURL=[NSURL URLWithString:path];
//NSData* myData=[NSData dataWithContentsOfURL:myURL];
NSData* myData;

[SDWebImageDownloader.sharedDownloader downloadImageWithURL:myURL
         options:0
        progress:^(NSInteger receivedSize, NSInteger expectedSize)
 
    DDLogInfo(@"Downloading...");
    // progression tracking code
 
        completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished)
 
    if (image && finished)
    
       DDLogInfo(@"Downloaded !");
       image = [[UIImage alloc] initWithData:myData];
    
 ];
...
return image;

感谢您的帮助。

【问题讨论】:

完成块返回图片,完成块前最后一个返回方法会被调用 我试图从完成块返回图像,但出现以下错误Control may reach end of a non-void block。接缝完全正常,因为根据文档downloadImageWithURL:options:progress:completed 无法返回UIImageView- (id <SDWebImageOperation>)downloadImageWithURL:(NSURL *)url options:(SDWebImageDownloaderOptions)options progress:(void (^)(NSInteger, NSInteger))progressBlock completed:(void (^)(UIImage *, NSData *, NSError *, BOOL))completedBlock 我搜索了这个,发现 downloadImageWithURL 没有任何返回类型(我的错)。我发现的是“downloadImageWithURL”方法,您可以使用该方法制作可以下载图像并设置为图像的自定义视图。例如(UIImageView+WebCache.h)。 对于您的情况,我认为“setImageWithURL”方法会起作用,让 SDWebCache 为您缓存图像。 【参考方案1】:

您可以尝试这个解决方案,而不是采用那种复杂的解决方案。创建名称为“DownloadImagesAsynchronously”的 NSObject 文件并将 .h 文件替换为以下内容。

#import <Foundation/Foundation.h>

@protocol NotifyParentProtocol <NSObject>

-(void)ImageDownloaded:(BOOL)_isDownloaded;

@end

@interface DownloadImagesAsynchronously : NSObject

    NSMutableData *receivedData;
    UIImageView *cCellImageView;
    NSURLConnection *imgDownloadConnection;

    id<NotifyParentProtocol> __weak delegate;


-(void) downloadImageAsynchornously:(NSString *)_imageURL andCellImage:(UIImageView *)_cellImgV;
@property(weak) id<NotifyParentProtocol> delegate;

@end

并将 .m 替换为以下代码

#import "DownloadImagesAsynchronously.h"


@implementation DownloadImagesAsynchronously

@synthesize delegate;

- (void)loadWithURL:(NSURL *)url

    NSURLConnection *conect = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:url]delegate:self];
    [conect start];


- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

    [receivedData setLength:0];


-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

    [receivedData appendData:data];


- (void)connectionDidFinishLoading:(NSURLConnection *)connection 

    cCellImageView.image = [UIImage imageWithData:receivedData];
    [cCellImageView.layer setCornerRadius:14.0f];
    [delegate ImageDownloaded:YES];


-(void) downloadImageAsynchornously:(NSString *)_imageURL andCellImage:(UIImageView *)_cellImage

    cCellImageView = _cellImage;
    receivedData = [[NSMutableData alloc] init];
    NSString *baseURL = @"http://example.com/abc/Gallary";
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@/%@",baseURL,_imageURL]];
    [self loadWithURL:url];


@end

现在像这样在你的 UIImageView 上调用,如果使用 TableView,它会延迟下载图像到每个 tableview 单元格

DownloadImagesAsynchronously *downloadAsynchImageObj = [[DownloadImagesAsynchronously alloc] init];
    downloadAsynchImageObj.delegate = self;
    [downloadAsynchImageObj downloadImageAsynchornously:model.ImageName1 andCellImage:self.mainImageView];

并实现委托方法。它会在下载图像时通知您。您可以执行所需的操作。

- (void)ImageDownloaded:(BOOL)_isDownloaded

// Image Downloaded.


如果您对此有任何疑问,希望这对您有用。请告诉我。谢谢

【讨论】:

【参考方案2】:

谢谢你们。

我混合了你的两个答案。我只是将我的UIImageView 传递给我的带有异步块的方法。

这是我的代码:

//view is an UIImageView coming directly from one of the parameters
if (view == nil) 
    myData=[NSData dataWithContentsOfURL:myURL];
    image = [[UIImage alloc] initWithData:myData];

else
    [SDWebImageDownloader.sharedDownloader downloadImageWithURL:myURL
                                                        options:0
                                                       progress:^(NSInteger receivedSize, NSInteger expectedSize)
     
         DDLogInfo(@"Downloading...");
         // progression tracking code
     
                                                      completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished)
     
         if (image && finished)
         
             DDLogInfo(@"Downloaded !");
             view.image = image;

         
     ];

现在我只有调整图片大小和比例的问题,但我原来的问题已经解决了。

我希望这对其他人有帮助。

【讨论】:

希望对您有所帮助:gist.github.com/YGeorge/d8df24f29c349ec21a44gist.github.com/YGeorge/8053506 它对我有帮助。它几乎是固定的,但我从你的例子中找到了灵感。谢谢!

以上是关于需要返回值的异步图像下载的主要内容,如果未能解决你的问题,请参考以下文章

改进异步封装:处理带返回值的异步调用

Kotlin 协程Flow 异步流 ① ( 以异步返回返回多个返回值 | 同步调用返回多个值的弊端 | 尝试在 sequence 中调用挂起函数返回多个返回值 | 协程中调用挂起函数返回集合 )

Kotlin 协程Flow 异步流 ① ( 以异步返回返回多个返回值 | 同步调用返回多个值的弊端 | 尝试在 sequence 中调用挂起函数返回多个返回值 | 协程中调用挂起函数返回集合 )

模板引擎不关心内容之——art-template,碰见的同步与fs.readFile异步以及函数回调问题的描述,针对fs的readfille读取文件时,返回不了异步函数返回值的解决方法

Java中使用有返回值的线程

net异步线程获取返回值的两种方式