ChatGPT解决这个技术问题 Extra ChatGPT

Can I load a UIImage from a URL?

I have a URL for an image (got it from UIImagePickerController) but I no longer have the image in memory (the URL was saved from a previous run of the app). Can I reload the UIImage from the URL again?

I see that UIImage has a imageWithContentsOfFile: but I have a URL. Can I use NSData's dataWithContentsOfURL: to read the URL?

EDIT1

based on @Daniel's answer I tried the following code but it doesn't work...

NSLog(@"%s %@", __PRETTY_FUNCTION__, photoURL);     
if (photoURL) {
    NSURL* aURL = [NSURL URLWithString:photoURL];
    NSData* data = [[NSData alloc] initWithContentsOfURL:aURL];
    self.photoImage = [UIImage imageWithData:data];
    [data release];
}

When I ran it the console shows:

-[PhotoBox willMoveToWindow:] file://localhost/Users/gary/Library/Application%20Support/iPhone%20Simulator/3.2/Media/DCIM/100APPLE/IMG_0004.JPG
*** -[NSURL length]: unrecognized selector sent to instance 0x536fbe0
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSURL length]: unrecognized selector sent to instance 0x536fbe0'

Looking at the call stack, I'm calling URLWithString, which calls URLWithString:relativeToURL:, then initWithString:relativeToURL:, then _CFStringIsLegalURLString, then CFStringGetLength, then forwarding_prep_0, then forwarding, then -[NSObject doesNotRecognizeSelector].

Any ideas why my NSString (photoURL's address is 0x536fbe0) doesn't respond to length? Why does it say it doesn't respond to -[NSURL length]? Doesn't it know that param is an NSString, not a NSURL?

EDIT2

OK, the only problem with the code is the string to URL conversion. If I hardcode the string, everything else works fine. So something is wrong with my NSString and if I can't figure it out, I guess that should go in as a different question. With this line inserted (I pasted the path from the console log above), it works fine:

photoURL = @"file://localhost/Users/gary/Library/Application%20Support/iPhone%20Simulator/3.2/Media/DCIM/100APPLE/IMG_0004.JPG";
It seems like photoURL is already an NSURL, not an NSString, given that NSLog handled it.
@drawn: Looks like an error in the docs. It says that UIImagePickerControllerMediaURL is an NSString but it's actually an NSURL object.
The library DLImageLoader is INCREDIBLE. rock solid, no doco, one command and everything is perfect. What a find.
I second (third?) DLImageLoader. I was skeptical about whether the comments about it on this page were objective - but I tried it anyway and it does work very nicely. I have a UIImageView within a UITableViewCell. All I did was replace the UIImageView with a DLImageView, then called the imageFromUrl: method to load the image, and it all just works -- asynchronous loading, caching, etc. Couldn't be easier.
DLImageLoader remains fantastic, another good one is Haneke, although it suffers a little from being not quite maintained.

K
Krishnabhadra

You can do it this way (synchronously, but compact):

UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:MyURL]]];

A much better approach is to use Apple's LazyTableImages to preserve interactivity.


Doesn't the data need to be converted from PNG (or JPG) file format to UIImage data? Or does UIImage figure that out somehow?
Guess I should just RTFM, it says right in UIImage Class Reference what file formats it can support and imageWithData: says it can be data from a file, sounds like it should work.
@Daniel: didn't work, I edited my question to include my actual code and the exception info. It's a little bizarre.
@Daniel: it does work if I use a string constant instead of the NSString I was passing in. So this latest problem was something wrong with my NSString, not a problem with the NSURL/NSData/UIImage code which works. Thanks Daniel!
If you're using just one image and you're looking for a quick fix you can just write a bit of code that caches the single image.
M
Muhammad Hassan Nasr

You can try SDWebImage, it provides:

Asynchronous loading Caching for offline use Place holder image to appear while loading Works well with UITableView

Quick example:

    [cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

I have modified that library a bit and integrated it with UIImage+Resize in order to add Resize/Crop capabilities to it. If you need that check it out at github.com/toptierlabs/ImageCacheResize
This example populates a UIImageView. SDWebImage also lets you populate a UIImage directly using SDWebImageManager - (void) downloadWithURL:.... See their example on the read me.
u
user3763002

And the swift version :

   let url = NSURL.URLWithString("http://live-wallpaper.net/iphone/img/app/i/p/iphone-4s-wallpapers-mobile-backgrounds-dark_2466f886de3472ef1fa968033f1da3e1_raw_1087fae1932cec8837695934b7eb1250_raw.jpg");
    var err: NSError?
    var imageData :NSData = NSData.dataWithContentsOfURL(url,options: NSDataReadingOptions.DataReadingMappedIfSafe, error: &err)
    var bgImage = UIImage(data:imageData)

D
Dhiraj Gupta

If you're really, absolutely positively sure that the NSURL is a file url, i.e. [url isFileURL] is guaranteed to return true in your case, then you can simply use:

[UIImage imageWithContentsOfFile:url.path]

F
Fattie

get DLImageLoader and try folowing code

   [DLImageLoader loadImageFromURL:imageURL
                          completed:^(NSError *error, NSData *imgData) {
                              imageView.image = [UIImage imageWithData:imgData];
                              [imageView setContentMode:UIViewContentModeCenter];

                          }];

Another typical real-world example of using DLImageLoader, which may help someone...

PFObject *aFacebookUser = [self.fbFriends objectAtIndex:thisRow];
NSString *facebookImageURL = [NSString stringWithFormat:
    @"http://graph.facebook.com/%@/picture?type=large",
    [aFacebookUser objectForKey:@"id"] ];

__weak UIImageView *loadMe = self.userSmallAvatarImage;
// ~~note~~ you my, but usually DO NOT, want a weak ref
[DLImageLoader loadImageFromURL:facebookImageURL
   completed:^(NSError *error, NSData *imgData)
    {
    if ( loadMe == nil ) return;

    if (error == nil)
        {
        UIImage *image = [UIImage imageWithData:imgData];
        image = [image ourImageScaler];
        loadMe.image = image;
        }
    else
        {
        // an error when loading the image from the net
        }
    }];

As I mention above another great library to consider these days is Haneke (unfortunately it's not as lightweight).


SDWebImage is the most popular library in Objective-C and KingFisher is the Swift port.
True , but DLImageLoader is better! :)
J
Jouhar

Try this code, you can set loading image with it, so the users knows that your app is loading an image from url:

UIImageView *yourImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"loading.png"]];
    [yourImageView setContentMode:UIViewContentModeScaleAspectFit];

    //Request image data from the URL:
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://yourdomain.com/yourimg.png"]];

        dispatch_async(dispatch_get_main_queue(), ^{
            if (imgData)
            {
                //Load the data into an UIImage:
                UIImage *image = [UIImage imageWithData:imgData];

                //Check if your image loaded successfully:
                if (image)
                {
                    yourImageView.image = image;
                }
                else
                {
                    //Failed to load the data into an UIImage:
                    yourImageView.image = [UIImage imageNamed:@"no-data-image.png"];
                }
            }
            else
            {
                //Failed to get the image data:
                yourImageView.image = [UIImage imageNamed:@"no-data-image.png"];
            }
        });
    });

I preferred this solution since it didn't require loading any 3rd party frameworks or instantiating data loading queues, etc.
m
marcc

Check out the AsyncImageView provided over here. Some good example code, and might even be usable right "out of the box" for you.


Interesting example, it's very similar in concept to Apple's LazyTableImages example mentioned in the earlier answer.
It's similar but beware that AsyncImageView really doesn't work in tables, at least not when you recycle table cells (as you should).
p
pauliephonic

AFNetworking provides async image loading into a UIImageView with placeholder support. It also supports async networking for working with APIs in general.


N
Nagarjun

Make sure enable this settings from iOS 9:

App Transport Security Settings in Info.plist to ensure loading image from URL so that it will allow download image and set it.

https://i.stack.imgur.com/k5rJX.png

And write this code:

NSURL *url = [[NSURL alloc]initWithString:@"http://feelgrafix.com/data/images/images-1.jpg"];
NSData *data =[NSData dataWithContentsOfURL:url];
quickViewImage.image = [UIImage imageWithData:data];

f
fpg1503

The way using a Swift Extension to UIImageView (source code here):

Creating Computed Property for Associated UIActivityIndicatorView

import Foundation
import UIKit
import ObjectiveC

private var activityIndicatorAssociationKey: UInt8 = 0

extension UIImageView {
    //Associated Object as Computed Property
    var activityIndicator: UIActivityIndicatorView! {
        get {
            return objc_getAssociatedObject(self, &activityIndicatorAssociationKey) as? UIActivityIndicatorView
        }
        set(newValue) {
            objc_setAssociatedObject(self, &activityIndicatorAssociationKey, newValue, UInt(OBJC_ASSOCIATION_RETAIN))
        }
    }

    private func ensureActivityIndicatorIsAnimating() {
        if (self.activityIndicator == nil) {
            self.activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
            self.activityIndicator.hidesWhenStopped = true
            let size = self.frame.size;
            self.activityIndicator.center = CGPoint(x: size.width/2, y: size.height/2);
            NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
                self.addSubview(self.activityIndicator)
                self.activityIndicator.startAnimating()
            })
        }
    }

Custom Initializer and Setter

    convenience init(URL: NSURL, errorImage: UIImage? = nil) {
        self.init()
        self.setImageFromURL(URL)
    }

    func setImageFromURL(URL: NSURL, errorImage: UIImage? = nil) {
        self.ensureActivityIndicatorIsAnimating()
        let downloadTask = NSURLSession.sharedSession().dataTaskWithURL(URL) {(data, response, error) in
            if (error == nil) {
                NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
                    self.activityIndicator.stopAnimating()
                    self.image = UIImage(data: data)
                })
            }
            else {
                self.image = errorImage
            }
        }
        downloadTask.resume()
    }
}

P
Peter Suwara

Local URL's are super simple, just use this :

UIImage(contentsOfFile: url.path)

j
jalmatari

The Best and easy way to load Image via Url is by this Code:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSData *data =[NSData dataWithContentsOfURL:[NSURL URLWithString:imgUrl]];

    dispatch_async(dispatch_get_main_queue(), ^{
        imgView.image= [UIImage imageWithData:data];
    });
});

Replace imgUrl by your ImageURL
Replace imgView by your UIImageView.

It will load the Image in another Thread, so It will not slow down your App load.


关注公众号,不定期副业成功案例分享
Follow WeChat

Success story sharing

Want to stay one step ahead of the latest teleworks?

Subscribe Now