Reputation: 2779
I am new to iOS development so please bear with me. I am trying to create a basic photo gallery but ran into a problem. When I started out with the project I just included all the images in my project. Now after having a lot more images(400+) I started loading them from a server. I made an array of images using the following line of code:
[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://www.testsite.com/testPic.png"]]]
Obviously making the user wait for an array of 400+ images to load from a server is unacceptable.
So my question is if I included one image in my project that said something like "Loading", how could I display that image until the actual image loaded from the server?
I'm making a basic grid-style photo gallery using a table-view and scroll-view. It loads up a few rows of small(thumbnail) images and when you click one it makes it full screen.
I'm using Xcode 4.3, ARC, and storyboards if that helps!
Sorry if this is confusing!
-Shredder2794
Upvotes: 0
Views: 1435
Reputation: 2543
A method is to subclass UIImageView
. When you allocate it you put a default image ( the loading one) or a UIActivityIndicator
, download the image you want to display ( in a separate thread) and when the image is downloaded display it. Have a look to NSURLRequest
and NSURLConnection
for the image download.
* EDIT *
Here is an example of code I developed. You can use this as a start point to develop your own loading image class. This class can be improved by using NSThread
for the image loading.
// ImageLoader.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
/**
* @brief Class that loads an UIImage from a server
* @author Nicolas
*/
@interface ImageLoader : UIView
{
@private
NSURLConnection *connection;
NSMutableData *data;
NSString *path;
UIActivityIndicatorView *loading;
UIImageView *imageView;
}
@property (nonatomic, retain) UIActivityIndicatorView *loading;
@property (nonatomic, retain) NSURLConnection *connection;
@property (nonatomic, retain) NSMutableData *data;
@property (nonatomic, retain) NSString *path;
@property (nonatomic, retain) UIImageView *imageView;
/**
* Load an image from a server an display it
* @param URL URL to get the image
* @param chemin path to save the image
* @author Nicolas
*/
- (void)loadImageFromUrl:(NSString *)URL forPath:(NSString *)chemin;
@end
// ImageLoader.m
#import "ImageLoader.h"
@implementation ImageLoader
@synthesize path, connection, data, loading, imageView;
- (id)init
{
self = [super init];
[self setUserInteractionEnabled:YES];
return self;
}
- (void)loadImageFromUrl:(NSString *)URL forPath:(NSString *)chemin
{
//if (connection != nil) [connection release];
//if (data != nil) [data release];
//if (path != nil) [path release];
self.path = chemin;
if ([[NSFileManager defaultManager] fileExistsAtPath:chemin])
{
if (imageView != nil)
{
[imageView removeFromSuperview];
[imageView release];
}
imageView = [[UIImageView alloc] initWithFrame:self.bounds];
imageView.image = [UIImage imageWithContentsOfFile:chemin];
[self addSubview:imageView];
}
else
{
loading = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 20.0f, 20.0f)];
loading.center = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
[loading setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
[loading startAnimating];
[self addSubview:loading];
NSURL *myURL = [NSURL URLWithString:[URL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:myURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0f];
connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}
}
#pragma mark -
#pragma mark NSURLConnection protocol
- (void)connection:(NSURLConnection *)_connection didReceiveData:(NSData *)_data
{
if (data == nil)
{
data = [[NSMutableData alloc] initWithCapacity:2048];
}
[data appendData:_data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)_connection
{
[data writeToFile:self.path atomically:YES];
if (imageView != nil)
{
[imageView removeFromSuperview];
[imageView release];
}
imageView = [[UIImageView alloc] initWithImage:[UIImage imageWithData:data]];
imageView.frame = self.bounds;
imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
[loading stopAnimating];
[loading setHidden:YES];
[self addSubview:imageView];
}
- (void)connection:(NSURLConnection *)_connection didFailWithError:(NSError *)error
{
[loading stopAnimating];
[loading release];
}
#pragma mark - Memory management
- (void)dealloc
{
[connection cancel];
[connection release];
[imageView release];
[path release];
[data release];
[super dealloc];
}
@end
Upvotes: 1
Reputation: 73966
The simplest way of doing this is to use AFNetworking, which provides setImageWithURL:placeholderImage:
in a category on UIImageView
(also a method with success/failure handlers).
Upvotes: 1