cristan lika
cristan lika

Reputation: 425

How to download image from web?

I am new to iOS i want download image to display it is working code but here lot of code duplication

let url = URL(string: iteminfo.imageUrl!)
    let urlRequest = URLRequest(url: url!)
    let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
        if error != nil {
            print(error)
        }
        if let data = data {
            print(data)
            self.imageViewItemPic.image  = UIImage(data: data)
        }
    }
    task.resume()
    let url2 = URL(string: iteminfo.cookerProfilePicUrl!)
    let urlRequest2 = URLRequest(url: url2!)
    let task2 = URLSession.shared.dataTask(with: urlRequest2) { (data, response, error) in
        if error != nil {
            print(error)
        }
        if let data = data {
            print(data)
            self.imageViewCookerProfilePic.image  = UIImage(data: data)
        }
    }
    task2.resume()

So I want to reuse my code but i unfortunately i can not reach my goal. there have no error and url is correct . every time goes else statement . i am missing something but what is that ?

        if let image = downlaodImage(urlImage: iteminfo.imageUrl){
            print("first \(image)")
              imageViewItemPic.image = image

        }else{
           print("first wrong......")
        }
        if let image =  downlaodImage(urlImage:  iteminfo.cookerProfilePicUrl){
            print("second \(image)")
             imageViewCookerProfilePic.image = image
        }
        else{
            print("second wrong......")
        }

Here is my method :

  func downlaodImage(urlImage : String?) -> UIImage?{
        var image : UIImage?
        let url = URL(string: urlImage!)
        let urlRequest = URLRequest(url: url!)

        let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in

            if let data = data {
               // print(data)

            image = UIImage(data: data)


            }
        }
        task.resume()
        return image
    }

note: I am not sure is it best way or not . if it is not best practice feel free to guide me .

Upvotes: 1

Views: 1238

Answers (3)

Adeel Miraj
Adeel Miraj

Reputation: 2496

There's no need of so much hassle. You have the URL of the image so you can simply download the image from the URL. For example:

func downloadImage(imageURL: String) {

    DispatchQueue.global().async {

        let data = NSData.init(contentsOf: NSURL.init(string: imageURL) as! URL)
        DispatchQueue.main.async {

            let image = UIImage.init(data: data as! Data)
            imageView.image = image
        }
    }
}

Edit: To reuse this code I would suggest to use extension of UIImageView. Here's an example:

extension UIImageView {

    func setImageFromURL(url: String) {

        DispatchQueue.global().async {

            let data = NSData.init(contentsOf: NSURL.init(string: url) as! URL)
            DispatchQueue.main.async {

                let image = UIImage.init(data: data as! Data)
                self.image = image
            }
        }
    }
}

Use this method whenever you want to set the image of an imageView from a url like this:

self.imageViewCookerProfilePic.setImageFromURL(url: "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQNpKmjx1w3DRDZ9IXN81-uhSUA6qL6obkOthoUkb9RZkXf5pJ8")

Upvotes: 1

Daniel Oram
Daniel Oram

Reputation: 8411

downlaodImage() downloads an image asynchronously so

if let image = downlaodImage(...) { ... }

is always going to fail because program execution has continued before your response data has come back.

It would be easier just to set your images in the callback function closure of downlaodImage() as below by adding a UIImageView parameter to downlaodImage(). This way you can reduce the repetition of if else blocks by moving them to the downlaodImage function.

func downlaodImage(urlImage : String?, imageView: UIImageView) -> UIImage?{
    var image : UIImage?
    let url = URL(string: urlImage!)
    let urlRequest = URLRequest(url: url!)

    let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in

        if let data = data {
           // print(data)

        if let image = UIImage(data: data) {
            imageView.image = image
        } else {
            print("failed to load image")
        }





        }
    }
    task.resume()
    return image
}

Simplified code without if/else blocks

downlaodImage(urlImage: "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQNpKmjx1w3DRDZ9IXN81-uhSUA6qL6obkOthoUkb9RZkXf5pJ8", imageView: imageViewItemPic)

downlaodImage(urlImage: "https://www.dominos.co.nz/ManagedAssets/OLO/eStore/all/Product/NZ/P015/P015_ProductImage_Small_en_Default_20140203_105245.png", imageView: imageViewCookerProfilePic)

Upvotes: 0

Alexey Tyurnin
Alexey Tyurnin

Reputation: 326

Dude. You should learn some staff about async and sync code. Here is the thing. Code in you downloadImage works synchronically, so it pass you URLTask and go straight to return, there you return you image variable, that is nil. One of the solutions in to use callback block like this:

func downloadImage(urlImage : String?, complete: ((UIImage?)->Void)? = nil){

    let url = URL(string: urlImage!)
    let urlRequest = URLRequest(url: url!)
    let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in

        if let data = data {
           complete?(UIImage(data: data))
        }
    }
    task.resume()
}

And then use it like this:

    { ...
        downloadImage(urlImage: "", complete: { image in
            if let image = image{
                self.imageViewItemPic.image = image
            }else{
                print("no image")
            }
        })
      ...
    }

You should read some tutorials about async code and web in swift. You could start with this site

Upvotes: 1

Related Questions