Russ
Russ

Reputation: 119

Default value for optional type 'URL?'

I have an extension allowing me to download images to my UITableView from API.

extension UIImageView {

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

            if error != nil {
                print(error)
                return
            }

            DispatchQueue.main.async {
                self.image = UIImage(data: data!)

            }
        }
        task.resume()
    }

}

The app crashes if imageUrl is nil.

How do I wrap it using ?? so the UIImageView is just blank if there’s no image?

This is a data model and fetch data function

class Article: NSObject {

    var headline: String?
    var date: String?
    var imageUrl: String?
    var desc: String?
    var url: String?

} 

@objc func fetchArticles() {
        let urlRequest = URLRequest(url: URL(string: "https://newsapi.org/v2/everything?pageSize=15&sortBy=publishedAt&apiKey=API_KEY")!)

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

            if error != nil {
                print(error)
                return
            }

            self.articles = [Article]()
            do {
                let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject]

                if let articlesFromJson = json["articles"] as? [[String: AnyObject]] {
                    for articlesFromJson in articlesFromJson {
                        let article = Article()
                        if
                            let title = articlesFromJson["title"] as? String,
                            let publishedAt = articlesFromJson["publishedAt"] as? String,
                            let urlToImage = articlesFromJson["urlToImage"] as? String,
                            let description = articlesFromJson["description"] as? String,
                            let url = articlesFromJson["url"] as? String

                        {

                            article.headline = title
                            article.date = publishedAt
                            article.imageUrl = urlToImage
                            article.desc = description
                            article.url = url


                        }
                        self.articles?.append(article) // and so on...

Upvotes: 6

Views: 9080

Answers (2)

Silas S. Caxias
Silas S. Caxias

Reputation: 96

I suggest you use a POD that downloads images asynchronously and always leaves an image of placeHolder, look at the following example that uses it:

import SDWebImage

imageView.sd_setImage (
   with: URL (string: "http://www.example.com/image.jpg"), 
   placeholderImage: UIImage (named: "placeholder.png") // define your default Image
)

Link para o POD: https://cocoapods.org/pods/SDWebImage

Upvotes: 0

Pratik Prajapati
Pratik Prajapati

Reputation: 1105

I have updated your extension and added a placeholder param. So when you pass an invalid URL, the guard will handle that case and set the default image to imageview.

extension UIImageView {
   func donwloadImage(from url: String, placerholder: UIImage? = UIImage(named: "your-default-image")) {
        guard let imageURL = URL(string: url) else {
            self.image = placeholder
            return
        }
        let urlRequest = URLRequest(url: imageURL)
        let task = URLSession.shared.dataTask(with: urlRequest) { (data,response,error) in
            DispatchQueue.main.async {
            guard let imageData = data, let image = UIImage(data: imageData) else {
                self.image = placerholder // it up to you to set placeholder image in case of error
                //handle error
                return
            }
            self.image = image
        }
       }
       task.resume()
    }
}

Upvotes: 0

Related Questions