Скачать изображение асинхронно - PullRequest
4 голосов
/ 19 марта 2012

Мне нужно загрузить изображение из Интернета и отобразить его в ImageView. В настоящее время я использую SDWebImage (это загрузчик асинхронных изображений с поддержкой кэша, с категорией UIImageView).

Но происходит сбой, когда я нажимаю кнопку «Назад» и «Вперед» (когда я пытаюсь несколько раз перейти назад и вперед). В любом случае это случается очень редко, но мне нужно избавиться от этой ошибки. Есть ли какая-либо другая библиотека (которая не использует частные API), которую я мог бы использовать в своем проекте?

Ответы [ 8 ]

10 голосов
/ 19 марта 2012

Да. Вы можете использовать другую библиотеку. Я уже реализовал это, используя AsyncImageView, который наследуется от UIImageView. Он сохраняет изображения в кэш-памяти, извлеченные из URL-адреса, и всякий раз, когда вам нужно загрузить изображение с того же URL-адреса , что и , он просто загружает его из кэш-памяти, что экономит много времени.

Просто перейдите по ссылке для реализации этого:

https://github.com/nicklockwood/AsyncImageView#readme

http://www.markj.net/iphone-asynchronous-table-image/

Пожалуйста, посмотрите на изображение, показывающее технику, которую я реализовал. Это позволяет вам выполнять другие действия во время загрузки изображений .:

enter image description here

6 голосов
/ 19 марта 2012

NSURLConnection обеспечивает асинхронную загрузку и встроена в iOS.

4 голосов
/ 19 марта 2012

Я лично использую встроенную функцию Grand Central Dispatch в iOS для асинхронной загрузки изображений с сервера.

Ниже приведен код, который я использовал для получения фотографий с Flickr в одном из моих приложений.

В вашем классе изображений / фотографий есть функция, подобная этой:

- (void)processImageDataWithBlock:(void (^)(NSData *imageData))processImage
{
NSString *url = self.imageURL;
dispatch_queue_t callerQueue = dispatch_get_current_queue();
dispatch_queue_t downloadQueue = dispatch_queue_create("Photo Downloader", NULL);
dispatch_async(downloadQueue, ^{
    NSData *imageData = *insert code that fetches photo from server*;
    dispatch_async(callerQueue, ^{
        processImage(imageData);
    });
});
dispatch_release(downloadQueue);
}

В контроллере просмотра фотографий вы можете вызвать эту функцию следующим образом:

- (void)viewWillAppear:(BOOL)animated
{
[spinner startAnimating];
[self.photo processImageDataWithBlock:^(NSData *imageData) {
    if (self.view.window) {
        UIImage *image = [UIImage imageWithData:imageData];
        imageView.image = image;
        imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height);
        scrollView.contentSize = image.size;
        [spinner stopAnimating];
    }
}];
}
4 голосов
/ 19 марта 2012

Я думаю, что ошибка, которую вы описываете, может произойти, потому что, когда вы «возвращаетесь», освобождаете некоторые объекты, которые могут быть делегатами соединений, которые все еще работают.Во избежание сбоев вы должны отменить соединения перед выпуском или освободить любой объект, который может быть делегатом работающего соединения.

Другой альтернативой для загрузки асинхронного образа является http://allseeing -i.com / ASIHTTPRequest/ .

2 голосов
/ 19 марта 2012

Проверьте EGOImageLoading от enormego для кэширования изображений. Он работает так же, как UIImageView и позволяет загружать изображения из HTTP асинхронно, а также легко интегрируется

2 голосов
/ 19 марта 2012
//JImage.h

#import <Foundation/Foundation.h>


@interface JImage : UIImageView {

    NSURLConnection *connection;

    NSMutableData* data;

    UIActivityIndicatorView *ai;
}

-(void)initWithImageAtURL:(NSURL*)url;  

@property (nonatomic, retain) NSURLConnection *connection;

@property (nonatomic, retain) NSMutableData* data;

@property (nonatomic, retain) UIActivityIndicatorView *ai;

@end



//JImage.m

#import "JImage.h"

@implementation JImage
@synthesize ai,connection, data;

-(void)initWithImageAtURL:(NSURL*)url {


    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;

    [self setContentMode:UIViewContentModeScaleToFill];

    if (!ai){

        [self setAi:[[UIActivityIndicatorView alloc]   initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge]]; 

        [ai startAnimating];

        [ai setFrame:CGRectMake(27.5, 27.5, 20, 20)];

        [ai setColor:[UIColor blackColor]];

        [self addSubview:ai];
    }
    NSURLRequest* request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60];

    connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];    
}


- (void)connection:(NSURLConnection *)theConnection didReceiveData:(NSData *)incrementalData {

if (data==nil) data = [[NSMutableData alloc] initWithCapacity:5000];

[data appendData:incrementalData];

NSNumber *resourceLength = [NSNumber numberWithUnsignedInteger:[data length]];

NSLog(@"resourceData length: %d", [resourceLength intValue]);

}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{
    NSLog(@"Connection error...");

    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

    [ai removeFromSuperview];

}
- (void)connectionDidFinishLoading:(NSURLConnection*)theConnection 
{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;

    [self setImage:[UIImage imageWithData: data]];

    [ai removeFromSuperview];   
}
@end



//Include the definition in your class where you want to use the image
-(UIImageView*)downloadImage:(NSURL*)url:(CGRect)frame {

JImage *photoImage=[[JImage alloc] init]; 

    photoImage.backgroundColor = [UIColor clearColor]; 

   [photoImage setFrame:frame];

   [photoImage setContentMode:UIViewContentModeScaleToFill]; 

    [photoImage initWithImageAtURL:url];

    return photoImage;
}


//How to call the class

UIImageView *imagV=[self downloadImage:url :rect]; 

//you can call the downloadImage function in looping statement and subview the returned  imageview. 
//it will help you in lazy loading of images.


//Hope this will help
1 голос
/ 05 марта 2014

Я знаю, что это очень старый поток, но в последнее время у меня было много случайных сбоев с SDWebImage, поэтому мне пришлось реализовать свой собственный механизм отложенной загрузки и кэширования. Это работает довольно хорошо, я просто не проверял это в случаях большой нагрузки. Итак, вот файлы .h и .m, за которыми я следую:

//  UIImageView+CustomCache.h
@interface UIImageView(CustomCache)

-(void)startAsyncDownload:(UIImage*)placeHolderImage imageUrlString:(NSString*)imageUrlString;
@end


//  UIImageView+CustomCache.m

#import "UIImageView+CustomCache.h"

@implementation UIImageView(CustomCache)

-(void)startAsyncDownload:(UIImage*)placeHolderImage imageUrlString:(NSString*)imageUrlString{
    self.image = placeHolderImage;
    [NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:
                                              [NSURL URLWithString:imageUrlString]] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionHandler){
        @autoreleasepool {
            if (connectionHandler != nil) {
                NSLog(@"error in downloading description %@",connectionHandler.localizedDescription);
            } else {
                ImagesCacheHandler *ref = [ImagesCacheHandler new];
                UIImage *imageFromData = [[UIImage alloc] initWithData:data];
                if (imageFromData != NULL && imageFromData != nil && data.length > 0) {
                    self.image = imageFromData;
//custom store to sqlite
                    [ref archiveImage:imageUrlString imageData:data moc:[ref fetchContext]];
                }
            }
        }
    }];
}

@end

И в моем табличном представлении я использую (я импортирую, конечно, UIImageView + CustomCache.h)

UIImageView *imageViewToLazyLoad = (UIImageView*)[cell viewWithTag:1];
[imageViewToLazyLoad startAsyncDownload:[UIImage imageNamed@"palce_Holder_Image_name"] imageUrlString:imageUrl];
0 голосов
/ 19 марта 2012

Я лично предпочитаю использовать NSURLConnection sendSynchronousRequest и помещать GCD-оболочку вокруг него. Содержит все в чистоте и порядке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...