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?
-
2Why would that be a problem? Once the image is downloaded you will know its size. You can also make the image view the size you want and stretch the image to fit. – David Rönnqvist Jun 10 '12 at 21:40
9 Answers
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;

- 10,016
- 3
- 33
- 46
-
Or set the size you want on the image view and just stretch the image once its downloaded to fit the image view. (You should stretch AND keep aspect, everything else looks weird) – David Rönnqvist Jun 10 '12 at 21:42
-
ah ok...but I don't understand how resize this image for my imageView; I sholud to create a miniature and I haven't a lot of space for my imageView (max 236 width and max 60 for height); in this space I should load image from url but it should be proportionate... – cyclingIsBetter Jun 10 '12 at 21:51
-
2I think what you want is to set the contentMode of the UIImageView to UIContentViewScaleAspectFit. But have a look at the documentation. – fbernardo Jun 10 '12 at 22:03
-
Thanks for this code. I have a question, how do I display a "loading" while the image is being retrieved and notify if the picture fails to download? – Shannon Cole Jul 10 '13 at 01:49
-
-
hey man. This line `NSData *data = [NSData dataWithContentsOfURL:url];` It is not very heavy for a cellForRowAtIndexPath? – jose920405 Sep 09 '15 at 14:07
-
not directly relevant to the question or answer, here, for getting size, instead of using last line in the code, CGSize size = img.size; use, int size = data.length; – mavericks Oct 06 '15 at 09:37
-
Is there a better way to get image size with alamofireimage? I want to do this same thing but with async – user805981 Jun 15 '16 at 20:21
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

- 102,010
- 123
- 446
- 597
In swift regarding using optionals:
var url:NSURL? = NSURL(string: imageString)
var data:NSData? = NSData(contentsOfURL : url!)
var image = UIImage(data : data!)

- 6,364
- 10
- 56
- 98
-
2This will crash if the image file is not at the specified image string. – Suragch Feb 06 '16 at 10:02
-
2Make use of if lets statements! This is unsafe code and will crash if url is nil – Harry Bloom Jul 19 '17 at 14:36
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()
}
}

- 19,892
- 8
- 68
- 68
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
}
}
}
}
}
}

- 1,456
- 12
- 27
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
}
}

- 1,218
- 9
- 11

- 634
- 9
- 11
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)")
}
}
}

- 584
- 5
- 6
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.
}

- 3,022
- 7
- 38
- 51

- 653
- 6
- 17
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)
}
}

- 634
- 9
- 11