iOS: load an image from url

IosUiimageviewUiimageNsurl

Ios Problem Overview


I need to load an image from a url and set it inside an UIImageView; the problem is that I don't know the exact size of the image, then how can I show the image correctly?

Ios Solutions


Solution 1 - Ios

Just use the size property of UIImage, for example:

NSURL *url = [NSURL URLWithString:path];
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *img = [[UIImage alloc] initWithData:data];
CGSize size = img.size;

Solution 2 - Ios

In swift:

var url = NSURL.URLWithString("http://www.example.com/picture.png")
var data = NSData(contentsOfURL : url)
var image = UIImage(data : data)
image.size // if you need it

Solution 3 - Ios

In swift regarding using optionals:

var url:NSURL? = NSURL(string: imageString)
var data:NSData? = NSData(contentsOfURL : url!)
var image = UIImage(data : data!)

Solution 4 - Ios

> IN SWIFT 3.0

The main thread must be always remain free so it serves the user interface and user interactions.

class ViewController: UIViewController {

@IBOutlet weak var imageView: UIImageView!

private func fetchImage() {
    let imageURL = URL(string: "https://i.stack.imgur.com/9z6nS.png")
    var image: UIImage?
    if let url = imageURL {
        //All network operations has to run on different thread(not on main thread).
        DispatchQueue.global(qos: .userInitiated).async {
            let imageData = NSData(contentsOf: url)
            //All UI operations has to run on main thread.
            DispatchQueue.main.async {
                if imageData != nil {
                    image = UIImage(data: imageData as! Data)
                    self.imageView.image = image
                    self.imageView.sizeToFit()
                } else {
                    image = nil
                }
            }
        }
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    fetchImage()
}

}

Solution 5 - Ios

To download Asynchronous image with Kingfisher library you can follow this step,url :https://github.com/onevcat/Kingfisher:

 func imageFromUrl(_ urlString: String) {
        if let url = URL(string: urlString) {
            ImageDownloader.default.downloadImage(with: url, options: [], progressBlock: nil) {
                (image, error, url, data) in
                DispatchQueue.main.async {
                    self.imageView.image = image
                }
            }
        }
    }

You can also download image with default URLSession.shared.dataTask

 func imageFromUrl(_ urlString: String) {
        if let url = URL(string: urlString) {
            let request = URLRequest(url: url)
            URLSession.shared.dataTask(with: request) {(data,response,error) in
                if let imageData = data as Data? {
                    if let img = UIImage(data: imageData){
                       DispatchQueue.main.async {
                       self.imageView.image = img
                       }
                    }
                }
            }
        }
    }

Solution 6 - Ios

SWIFT 5.0 + fetch on background

private func fetchImage(_ photoURL: URL?) {

    guard let imageURL = photoURL else { return  }

    DispatchQueue.global(qos: .userInitiated).async {
        do{
            let imageData: Data = try Data(contentsOf: imageURL)

            DispatchQueue.main.async {
                let image = UIImage(data: imageData)
                self.userImageView.image = image
                self.userImageView.sizeToFit()
                self.tableView.reloadData()
            }
        }catch{
            print("Unable to load data: \(error)")
        }
    }
}

Solution 7 - Ios

One common mistake in displaying an image downloaded from json or a url is the problem of queues. ALL UI-related things need to be done in the main queue, so if you forgot this, even perfect code (above answers are good) won't display your image on occasion. To call the mainQueue, use code like this, and note that calling main queue might need to be done seperately in the called imageDisplay function:

dispatch_async(dispatch_get_main_queue(), ^{

    self.nameLabel.text = self.pokemon.name;

    [self displayImage];  //CALLS FUNCTION
    self.abilitiesTextView.text = @"loves SwiftUI";
});

- (void)displayImage {            
    
    NSString *imageURLString = [NSString stringWithFormat: self.pokemon.sprite];
    NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:imageURLString]];
    dispatch_async(dispatch_get_main_queue(), ^{
        self.spriteImageView.image = [UIImage  imageWithData: imageData];
    });

    // NOTE: important for newer versions of XCode/Obj-C...
    //[imageData release];   With ARC ("automated release..."), release method is forbidden, it's already done for you.
}

Solution 8 - Ios

Swift safe code version:

private func loadImage(from url:URL) -> UIImage? {
    let imageData: Data
    
    do {
        imageData = try Data(contentsOf: url)
    } catch {
        return nil
    }
    
    return UIImage(data: imageData)
}

private func loadImage(from urlString:String) -> UIImage? {
    guard let url = URL(string: urlString) else {
        return nil
    }
    
    return self.loadImage(from: url)
}

Keep in mind that this code blocks the main thread, so you should run it on a background thread. For example:

DispatchQueue.global().async {
    let image = UIImage(fromFile: "http://xpto.com/image.png")
    
    // And then you should update UI on main thread.
    // If you have an UIImageView outlet you can update its image this way:
    DispatchQueue.main.async {
        imageView.image = image
        imageView.contentMode = .scaleAspectFit
    }
}

Solution 9 - Ios

If you prefer you can even move it to an UIImage extension:

extension UIImage {
    
    //NOTE: This is not thread safe, please run it on a background thread.
    convenience init?(fromFile filePath:String) {
        guard let url = URL(string: filePath) else {
            return nil
        }
        
        self.init(fromURL: url)
    }
    
    //NOTE: This is not thread safe, please run it on a background thread.
    convenience init?(fromURL url:URL) {
        let imageData: Data
        
        do {
            imageData = try Data(contentsOf: url)
        } catch {
            return nil
        }
        
        self.init(data: imageData)
    }
    
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestioncyclingIsBetterView Question on Stackoverflow
Solution 1 - IosfbernardoView Answer on Stackoverflow
Solution 2 - Iosyegor256View Answer on Stackoverflow
Solution 3 - IostheDCView Answer on Stackoverflow
Solution 4 - IosAshok RView Answer on Stackoverflow
Solution 5 - IosKrishna Kumar ThakurView Answer on Stackoverflow
Solution 6 - IosBary LevyView Answer on Stackoverflow
Solution 7 - IosJohn PittsView Answer on Stackoverflow
Solution 8 - IosRicardo BarrosoView Answer on Stackoverflow
Solution 9 - IosRicardo BarrosoView Answer on Stackoverflow