Hi,
Here I'm placing code for LazyLoading of Images in iPhone/iPad/iOS Application. Please go through it. It'll surely help you.
Step 1: Create "DTLazyImageView.h"
@class DTLazyImageView;
@protocol DTLazyImageViewDelegate <NSObject>
@optional
- (void)lazyImageView:(DTLazyImageView *)lazyImageView didChangeImageSize:(CGSize)size;
- (void)imageDidLoad: (DTLazyImageView *) lazyImageView;
@end
@interface DTLazyImageView : UIImageView
{
UIActivityIndicatorView *actv;
}
@property (nonatomic, strong) NSURL *url;
@property (nonatomic, assign) BOOL shouldShowProgressiveDownload;
@property (nonatomic, strong) UIActivityIndicatorView *actv;
@property (nonatomic, assign) id<DTLazyImageViewDelegate> delegate; // subtle simulator bug - use assign not __unsafe_unretained
- (void)startLoading;
- (void)cancelLoading;
- (void)loadImageAtURL:(NSURL *)url;
@end
Step 2: Create "DTLazyImageView.m" file.
#import "DTLazyImageView.h"
static NSCache *_imageCache = nil;
@interface DTLazyImageView ()
- (void)notify;
@end
@implementation DTLazyImageView
{
NSURL *_url;
NSURLConnection *_connection;
NSMutableData *_receivedData;
CGFloat _fullHeight;
CGFloat _fullWidth;
NSUInteger _expectedSize;
BOOL shouldShowProgressiveDownload;
__unsafe_unretained id<DTLazyImageViewDelegate> _delegate;
}
@synthesize delegate=_delegate;
- (void)dealloc
{
[_connection cancel];
actv = nil;
}
- (void) startLoading
{
NSLog(@"Tag: %d , Url :%@",self.tag,[_url absoluteString]);
if (!self.image && [[_url absoluteString] length]>0)
{
UIImage *image = [_imageCache objectForKey:_url];
actv = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
actv.frame = CGRectMake(50.0, 50.0, 20.0, 20.0);
[self addSubview:actv];
if (image)
{
self.image = image;
_fullWidth = image.size.width;
_fullHeight = image.size.height;
// for unknown reasons direct notify does not work below iOS 5
[self performSelector:@selector(notify) withObject:nil afterDelay:0.0];
return;
}
[self loadImageAtURL:_url];
}
else
{
UIImage *image = [UIImage imageNamed:@"logo.png"];
self.image = image;
_fullWidth = image.size.width;
_fullHeight = image.size.height;
}
}
- (void)loadImageAtURL:(NSURL *)url
{
[self performSelectorInBackground:@selector(loadImage:) withObject:url];
}
- (void)loadImage:(NSURL *)url
{
@autoreleasepool
{
[actv startAnimating];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:60.0];
_connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
[_connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
[_connection start];
// necessary because otherwise otherwise the delegate methods would not get delivered
CFRunLoopRun();
}
}
- (void)didMoveToSuperview
{
[super didMoveToSuperview];
}
- (void)cancelLoading
{
[_connection cancel];
_connection = nil;
_receivedData = nil;
}
#pragma mark NSURL Loading
- (void)notify
{
[self.delegate imageDidLoad:self];
}
- (void)completeDownloadWithData:(NSData *)data
{
UIImage *image = [[UIImage alloc] initWithData:data];
self.image = image;
_fullWidth = image.size.width;
_fullHeight = image.size.height;
[self notify];
[actv stopAnimating];
[actv removeFromSuperview];
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
_imageCache = [[NSCache alloc] init];
});
if (_url)
{
// cache image
[_imageCache setObject:image forKey:_url];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// every time we get an response it might be a forward, so we discard what data we have
_receivedData = nil;
// does not fire for local file URLs
if ([response isKindOfClass:[NSHTTPURLResponse class]])
{
NSHTTPURLResponse *httpResponse = (id)response;
if (![[httpResponse MIMEType] hasPrefix:@"image"])
{
[self cancelLoading];
return;
}
}
/* For progressive download */
_fullWidth = _fullHeight = -1.0f;
_expectedSize = (NSUInteger)[response expectedContentLength];
_receivedData = [[NSMutableData alloc] init];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[_receivedData appendData:data];
}
- (void)removeFromSuperview
{
[super removeFromSuperview];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if (_receivedData)
{
[self performSelectorOnMainThread:@selector(completeDownloadWithData:) withObject:_receivedData waitUntilDone:YES];
_receivedData = nil;
}
_connection = nil;
CFRunLoopStop(CFRunLoopGetCurrent());
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
_connection = nil;
_receivedData = nil;
CFRunLoopStop(CFRunLoopGetCurrent());
}
#pragma mark Properties
@synthesize url = _url;
@synthesize shouldShowProgressiveDownload;
@synthesize actv;
@end
Step 3: DO the following steps to your current controller where you want to use LazyImageLoad.
#import "DTLazyImageView.h"
@interface RootViewController : UIViewController<DTLazyImageViewDelegate> {
DTLazyImageView *lazyImageView;
}
@end
@implementation RootViewController
-(void)viewWillAppear:(BOOL)animated
{
for(int i=0;i<5;i++)
{
DTLazyImageView *lazyImageView = [[DTLazyImageView alloc] init];
lazyImageView.delegate = self;
lazyImageView.tag = i;
lazyImageView.frame = CGRectMake(x, y,width, height);
lazyImageView.url = [NSURL URLWithString:@"put image url here"];
[self.view addSubview:lazyImageView];
if (! lazyImageView.image) {
[lazyImageView startLoading];
}
}
}
#pragma mark -
#pragma mark DTLazyImageView Delegate Method
- (void)imageDidLoad: (DTLazyImageView *) lazyImageView
{
// place your custom code here
}
@end
Note : Using above steps you can easily, implement LazyLoad of images to your application.
Feel free to ask, if any Query.
Thanks & Regards,
Nilesh Prajapati
Here I'm placing code for LazyLoading of Images in iPhone/iPad/iOS Application. Please go through it. It'll surely help you.
Step 1: Create "DTLazyImageView.h"
@class DTLazyImageView;
@protocol DTLazyImageViewDelegate <NSObject>
@optional
- (void)lazyImageView:(DTLazyImageView *)lazyImageView didChangeImageSize:(CGSize)size;
- (void)imageDidLoad: (DTLazyImageView *) lazyImageView;
@end
@interface DTLazyImageView : UIImageView
{
UIActivityIndicatorView *actv;
}
@property (nonatomic, strong) NSURL *url;
@property (nonatomic, assign) BOOL shouldShowProgressiveDownload;
@property (nonatomic, strong) UIActivityIndicatorView *actv;
@property (nonatomic, assign) id<DTLazyImageViewDelegate> delegate; // subtle simulator bug - use assign not __unsafe_unretained
- (void)startLoading;
- (void)cancelLoading;
- (void)loadImageAtURL:(NSURL *)url;
@end
Step 2: Create "DTLazyImageView.m" file.
#import "DTLazyImageView.h"
static NSCache *_imageCache = nil;
@interface DTLazyImageView ()
- (void)notify;
@end
@implementation DTLazyImageView
{
NSURL *_url;
NSURLConnection *_connection;
NSMutableData *_receivedData;
CGFloat _fullHeight;
CGFloat _fullWidth;
NSUInteger _expectedSize;
BOOL shouldShowProgressiveDownload;
__unsafe_unretained id<DTLazyImageViewDelegate> _delegate;
}
@synthesize delegate=_delegate;
- (void)dealloc
{
[_connection cancel];
actv = nil;
}
- (void) startLoading
{
NSLog(@"Tag: %d , Url :%@",self.tag,[_url absoluteString]);
if (!self.image && [[_url absoluteString] length]>0)
{
UIImage *image = [_imageCache objectForKey:_url];
actv = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
actv.frame = CGRectMake(50.0, 50.0, 20.0, 20.0);
[self addSubview:actv];
if (image)
{
self.image = image;
_fullWidth = image.size.width;
_fullHeight = image.size.height;
// for unknown reasons direct notify does not work below iOS 5
[self performSelector:@selector(notify) withObject:nil afterDelay:0.0];
return;
}
[self loadImageAtURL:_url];
}
else
{
UIImage *image = [UIImage imageNamed:@"logo.png"];
self.image = image;
_fullWidth = image.size.width;
_fullHeight = image.size.height;
}
}
- (void)loadImageAtURL:(NSURL *)url
{
[self performSelectorInBackground:@selector(loadImage:) withObject:url];
}
- (void)loadImage:(NSURL *)url
{
@autoreleasepool
{
[actv startAnimating];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:60.0];
_connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
[_connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
[_connection start];
// necessary because otherwise otherwise the delegate methods would not get delivered
CFRunLoopRun();
}
}
- (void)didMoveToSuperview
{
[super didMoveToSuperview];
}
- (void)cancelLoading
{
[_connection cancel];
_connection = nil;
_receivedData = nil;
}
#pragma mark NSURL Loading
- (void)notify
{
[self.delegate imageDidLoad:self];
}
- (void)completeDownloadWithData:(NSData *)data
{
UIImage *image = [[UIImage alloc] initWithData:data];
self.image = image;
_fullWidth = image.size.width;
_fullHeight = image.size.height;
[self notify];
[actv stopAnimating];
[actv removeFromSuperview];
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
_imageCache = [[NSCache alloc] init];
});
if (_url)
{
// cache image
[_imageCache setObject:image forKey:_url];
}
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// every time we get an response it might be a forward, so we discard what data we have
_receivedData = nil;
// does not fire for local file URLs
if ([response isKindOfClass:[NSHTTPURLResponse class]])
{
NSHTTPURLResponse *httpResponse = (id)response;
if (![[httpResponse MIMEType] hasPrefix:@"image"])
{
[self cancelLoading];
return;
}
}
/* For progressive download */
_fullWidth = _fullHeight = -1.0f;
_expectedSize = (NSUInteger)[response expectedContentLength];
_receivedData = [[NSMutableData alloc] init];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[_receivedData appendData:data];
}
- (void)removeFromSuperview
{
[super removeFromSuperview];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if (_receivedData)
{
[self performSelectorOnMainThread:@selector(completeDownloadWithData:) withObject:_receivedData waitUntilDone:YES];
_receivedData = nil;
}
_connection = nil;
CFRunLoopStop(CFRunLoopGetCurrent());
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
_connection = nil;
_receivedData = nil;
CFRunLoopStop(CFRunLoopGetCurrent());
}
#pragma mark Properties
@synthesize url = _url;
@synthesize shouldShowProgressiveDownload;
@synthesize actv;
@end
Step 3: DO the following steps to your current controller where you want to use LazyImageLoad.
#import "DTLazyImageView.h"
@interface RootViewController : UIViewController<DTLazyImageViewDelegate> {
DTLazyImageView *lazyImageView;
}
@end
@implementation RootViewController
-(void)viewWillAppear:(BOOL)animated
{
for(int i=0;i<5;i++)
{
DTLazyImageView *lazyImageView = [[DTLazyImageView alloc] init];
lazyImageView.delegate = self;
lazyImageView.tag = i;
lazyImageView.frame = CGRectMake(x, y,width, height);
lazyImageView.url = [NSURL URLWithString:@"put image url here"];
[self.view addSubview:lazyImageView];
if (! lazyImageView.image) {
[lazyImageView startLoading];
}
}
}
#pragma mark -
#pragma mark DTLazyImageView Delegate Method
- (void)imageDidLoad: (DTLazyImageView *) lazyImageView
{
// place your custom code here
}
@end
Note : Using above steps you can easily, implement LazyLoad of images to your application.
Feel free to ask, if any Query.
Thanks & Regards,
Nilesh Prajapati
No comments:
Post a Comment