56

I'm trying to get an image from an URL and it doesn't seem to be working for me. Can someone point me in the right direction?

Here is my code:

NSURL *url = [NSURL URLWithString:@"http://myurl/mypic.jpg"];

NSString *newIMAGE = [[NSString alloc] initWithContentsOfURL:url
                                       encoding:NSUTF8StringEncoding error:nil];

cell.image = [UIImage imageNamed:newIMAGE];

When I debug the newIMAGE string is nil so something isn't working there.

5 Answers 5

174

What you want is to get the image data, then initialize a UIImage using that data:

NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: @"http://myurl/mypic.jpg"]];
cell.image = [UIImage imageWithData: imageData];
[imageData release];

As requested, here's an asynchronous version:

dispatch_async(dispatch_get_global_queue(0,0), ^{
    NSData * data = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: @"http://myurl/mypic.jpg"]];
    if ( data == nil )
        return;
    dispatch_async(dispatch_get_main_queue(), ^{
        // WARNING: is the cell still using the same data by this point??
        cell.image = [UIImage imageWithData: data];
    });
    [data release];
});
Sign up to request clarification or add additional context in comments.

3 Comments

this is synchronous , can you please add a code to download it in background , because, it bloques the ui thread
A couple of problems: 1. You have a comment about making sure the cell is still visible. You do that with UITableViewCell *updateCell = [tableView cellForRowAtIndexPath:indexPath]; followed by if (updateCell) ... (and obviously, use this updateCell rather than the original cell for your update of the imageView; 2. Make sure, if doing asynchronously, to initialize the image property for your imageView before you initiate the asynchronous retrieval process; 3. You really should do caching, so it doesn't have to re-retrieve it every time you scroll back to a previously loaded image.
Rob posted clear code example for points 1 & 2 above at -> stackoverflow.com/questions/16663618/… (thank you Rob)
5

Ok there's a couple of things wrong here:

  1. The conversion from URL (url) to NSString (newImage) is incorrect, what the code actually does there is try to load the contents of "http://myurl/mypic.jpg" into the NSString.

  2. The -imageNamed method takes a string that is a path of a local file, not a URL as an argument.

You need to use an NSData object as an intermediary, like in this example: http://blogs.oreilly.com/digitalmedia/2008/02/creating-an-uiimage-from-a-url.html

Comments

4

the accepted answer asynchronous version worked very slow in my code. an approach using NSOperation worked light years faster. the code provided by Joe Masilotti --> objective - C : Loading image from URL? (and pasted below):

-(void) someMethod {
    // set placeholder image
    UIImage* memberPhoto = [UIImage imageNamed:@"place_holder_image.png"];

    // retrieve image for cell in using NSOperation
    NSURL *url = [NSURL URLWithString:group.photo_link[indexPath.row]];
    [self loadImage:url];
}

- (void)loadImage:(NSURL *)imageURL
{
    NSOperationQueue *queue = [NSOperationQueue new];
    NSInvocationOperation *operation = [[NSInvocationOperation alloc]
                                        initWithTarget:self
                                        selector:@selector(requestRemoteImage:)
                                        object:imageURL];
    [queue addOperation:operation];
}

- (void)requestRemoteImage:(NSURL *)imageURL
{
    NSData *imageData = [[NSData alloc] initWithContentsOfURL:imageURL];
    UIImage *image = [[UIImage alloc] initWithData:imageData];

    [self performSelectorOnMainThread:@selector(placeImageInUI:) withObject:image waitUntilDone:YES];
}

- (void)placeImageInUI:(UIImage *)image
{
    [self.memberPhotoImage setImage:image];
}

Comments

1

In Swift 3 and 4

let theURL = URL(string:"https://exampleURL.com")
let imagedData = NSData(contentsOf: theURL!)!
let theImage = UIImage(data: imagedData as Data)
cell.theImageView.image = theImage

This will be done in the main thread.

And to perform the same in asynchronous/background thread

   DispatchQueue.main.async(){
      let theURL = URL(string:"https://exampleURL.com")
      let imagedData = NSData(contentsOf: theURL!)!
      let theImage = UIImage(data: imagedData as Data)
   }
   cell.theImageView.image = theImage

Comments

1

Updating upon Jim dovey answer,[data release] is no longer required because in the updated apple guidelines. Memory management is done automatically by ARC (Automatic counting reference) ,

Here is the updated asynchronous call,

dispatch_async(dispatch_get_global_queue(0,0), ^{
        NSData * data = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: @"your_URL"]];
        if ( data == nil )
            return;
        dispatch_async(dispatch_get_main_queue(), ^{
            self.your_UIimage.image = [UIImage imageWithData: data];
        });

    });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.