iPhone: How to get a UIImage from a url?
Solution 1
NSURL *url = [NSURL URLWithString:@"http://example.com/image.jpg"];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [[[UIImage alloc] initWithData:data] autorelease];
However, this isn't asynchronous.
Solution 2
You should keep in mind that loading the image data with the sample code you've provided in your own answer will block the main thread until the download has completed. This is a useability no-no. The users of your app will think your app is unresponsive. If you want to download an image, prefer NSURLConnection to download it asynchronously in its own thread.
Read the Apple documentation about async downloads with NSURLConnection.
When your download completes, you can then instantiate your UIImage from the data object:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if (requestData)
{
self.image = [[[UIImage alloc] initWithData:requestData] autorelease];
}
}
Where requestData
and image
are instance variables of your containing class, and image
is a retained property. Be sure to release image
in the dealloc
routine of the class, e.g. using self.image=nil;
.
Solution 3
It is true that Asynchronous loading is a must, but you can also achieve that with a background call if you just need a simple solution.
[self performSelectorInBackground:@selector(loadImage) withObject:nil];
- (void)loadImage
{
NSURL * url = [NSURL URLWithString:@"http://.../....jpg"];
NSData * data = [NSData dataWithContentsOfURL:url];
UIImage * image = [UIImage imageWithData:data];
if (image)
{
// Success use the image
...
}
else
{
// Failed (load an error image?)
...
}
}
Solution 4
You can load an image in a UIImageView
from a URL without blocking the UI thread simply using the dispatch_async
:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSURL *url = [NSURL URLWithString:myURL];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage* image = [[UIImage alloc]initWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
[myImageView setImage:image];
});
});
The first dispatch_async
is used to load the image from the URL in background (without blocking the UI). The second dispatch_async
is used to actually inject the image just loaded in the UIImageView
. Please, note that the second dispatch_async
is designed to work on the main thread (the UI thread) that is, indeed, the thread used to update the UI.
Solution 5
There is a really good example here using blocks: http://ios-blog.co.uk/iphone-development-tutorials/uiimage-from-url-%E2%80%93-simplified-using-blocks/
Comments
-
philfreo almost 4 years
How do you download an image and turn it into a UIImage?
-
philfreo over 14 yearsExcellent point. I was just looking at this also: markj.net/iphone-asynchronous-table-image
-
Andrew Zimmer over 12 yearsThis is an absolute must. Here are a couple of classes that handle asynchronous UIImage loading and caching using blocks. t.co/ovOn86KG
-
Rob Reuss over 12 yearsAndrew - using your block-based approach, is the resulting UIImage being returned on a background thread? If so, I think that when assigning that to an UIImageView it would need to be explicitly done so on the main thread using performSelectorOnMainThread - yes?
-
Tony over 11 yearsTake a look at the couple of libraries in my answer. I have been using it in a project and works great.