Jorge Zapata
Jorge Zapata

Reputation: 121

How can I use a URL for an image in Swift?

I am trying to retrieve certain data from my Firebase Database - the profile image. As you can see, this is from a UITableViewCell. I have an @IBOutlet for my imageView I want to cover.

As the view awakens, you can see that I go through, and make sure that I can get the information. I know how to retrieve data from Firebase, but not photo URLs, and then convert to the photo itself.

I'm not sure why it isn't working. I am getting an error, and will show it below. There is a possibility it is because of the URL unwrapping stuff, or as if the Firebase isn't formatted correctly, which I think it is, though.

Error Message : Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

import UIKit
import FirebaseAuth
import FirebaseDatabase
import Firebase

class ProfileCellControler: UITableViewCell {

    @IBOutlet var name : UILabel!
    @IBOutlet var rating : UILabel!
    @IBOutlet var imageViewPro : UIImageView!

    var databaseRefer : DatabaseReference!
    var databaseHandle : DatabaseHandle!

    override func awakeFromNib() {
        super.awakeFromNib()

        var urlString = ""
        let urll = URL(string: urlString)!

        databaseRefer = Database.database().reference()
        let userID = Auth.auth().currentUser!.uid

        databaseHandle = databaseRefer.child("Users").child(userID).child("Profile").child("Profile Name").observe(.value, with: { (data) in
            print(String((data.value as? String)!))
            self.name.text = "\(String((data.value as? String)!))"
            print("Done")
        })

        databaseHandle = databaseRefer.child("Users").child(userID).child("Profile").child("Stars").observe(.value, with: { (data) in
            print(String((data.value as? String)!))
            if ((String((data.value as? String)!)) == "N/A") {
                self.rating.text = "No Rating"
            } else {
                self.rating.text = "\(String((data.value as? String)!)) ★"
            }
            print("Done")
        })

        databaseHandle = databaseRefer.child("Users").child(userID).child("Profile").child("Profile Image").observe(.value, with: { (data) in
            print(String((data.value as? String)!))
            print("Done \(String((data.value as? String)!))")
            urlString = (String((data.value as? String)!))
        })

        ImageService.downloadImage(withURL: urll) { (image) in
            self.imageViewPro.image = image
        }

        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}

Take a look at my code, and use the code here if you don't understand

Upvotes: 1

Views: 183

Answers (2)

janaz
janaz

Reputation: 703

Import KingFisher to make your life easier and then..

  1. Download string representation of image from Firebase asynchronically.
  2. Assign downloaded image to imageView with .kf.setImage method.

Upvotes: 0

TheRedCamaro3.0 3.0
TheRedCamaro3.0 3.0

Reputation: 831

The string for the URL is found nil because you are creating the call to download the image for your url before the urll has been initialized with a value from the database in:

  databaseHandle = databaseRefer.child("Users").child(userID).child("Profile").child("Profile Image").observe(.value, with: { (data) in
            print(String((data.value as? String)!))
            print("Done \(String((data.value as? String)!))")
            urlString = (String((data.value as? String)!))
        })

observe(.value, with: ) Is an asynchronous operation thus

ImageService.downloadImage(withURL: urll) { (image) in
            self.imageViewPro.image = image
    }

Is being called before observe(.value, with:) is resolved. I would recommend moving the callback for the download URL inside of the completion for .observe(:value, :with) or using grand central dispatch to control the flow better.

As a side note, I highly recommend SDWebImage for handling your image downloading needs as it is configurable with a default image for situations such as this when the image fails to load.

Upvotes: 1

Related Questions