Icculus Icculus - 2 months ago 22
iOS Question

Getting images from Firebase JSON

I was wondering if it were possible to fetch an image from the Firebase Database? I know that I can use the storage but for my particular situation it needs to be altered a lot and would be a lot easier if I could enter in the information into the JSON tree and fetch it that way.

So in short, my question is can I use the URL from the storage section of Firebase and copy and paste that into a child in the JSON tree and retrieve it as I would any other number or string in the database?

Every time I code it out it says trying to unwrap a nil value which means it is not finding the image that the URL is pointing to, I assume.

Thanks in advance. Here is the Fetch code that I am using:

let newsimage1 = cell.viewWithTag(3) as! UIImageView
let fetch2 = BASE_URL.child("/AA News Feed 1/Image")
fetch2.observeEventType(.Value, withBlock: { snapshot in
let base64EncodedString = snapshot.value
let imageData = NSData(base64EncodedString: base64EncodedString as! String,
options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
let decodedImage = UIImage(data:imageData!)!
newsimage1.image = decodedImage
}, withCancelBlock: { error in
print(error.description)
})

Answer

The method you suggested is generally how you'd retrieve an image from Firebase. You simply store the URL in your FirebaseDatabase then use it to retrieve the image from FirebaseStorage.

General Setup

var storageRootRef: FIRStorageReference!
var databaseRootRef: FIRDatabaseReference!

override func viewDidLoad()
{
    super.viewDidLoad()

    storageRootRef = FIRStorage.storage().reference()
    databaseRootRef = FIRDatabase.database().reference()
}

Image Saving

You first need to save the image to FirebaseStorage then retrieve the downloadURL of its location, then only can you go ahead and write this info into your FirebaseDatabase as shown below

Swift 2

func createUserToDatabase()
{
    storageRootRef = storageRootRef.child("ProfileImages").child(self.currentUser.uid + ".png")

    if let imageData = UIImagePNGRepresentation(currentUser.profileImage)
    {
        storageRootRef.putData(imageData, metadata: nil, completion: { (metadata: FIRStorageMetadata?, error: NSError?) in

            if let storageError = error
            {
                print("Firebase Upload Error")
                print(storageError.localizedDescription)
                return
            }
            else if let storageMetadata = metadata
            {
                if let imageURL = storageMetadata.downloadURL()
                {
                    self.currentUser.profileImageURL = imageURL.absoluteString
                    // TODO: Now you may write to your Firebase Database since you already have the imageURL stored.
                }
            }
        })
    }
}

Swift 3

func createUserToDatabase()
{
    storageRootRef = storageRootRef.child("ProfileImages").child(self.currentUser.uid + ".png")

    if let imageData = UIImagePNGRepresentation(currentUser.profileImage)
    {
        storageRootRef.put(imageData, metadata: nil, completion: { (metadata: FIRStorageMetadata?, error: Error?) in

            if let storageError = error
            {
                print("Firebase Upload Error")
                print(storageError.localizedDescription)
                return
            }
            else if let storageMetadata = metadata
            {
                if let imageURL = storageMetadata.downloadURL()
                {
                    self.currentUser.profileImageURL = imageURL.absoluteString
                    // TODO: Now you may write to your Firebase Database since you already have the imageURL stored.
                }
            }
        })
    }
}

Image Retrieval

Simply query into your FirebaseDatabase for the imageURL, then initiate a URLSession for its retrieval as shown below.

Swift 2

func retrieveUserData()
{
    databaseRootRef!.child("path").observeSingleEventOfType(
    .Value) { (snapshot: FIRDataSnapshot) in

        if let firebaseValue = snapshot.value
        {
            self.currentUser.profileImageURL = firebaseValue["profileImageURL"] as! String
        }

        let imageURL: NSURL = NSURL(string: self.currentUser.profileImageURL)!

        NSURLSession.sharedSession().dataTaskWithURL(imageURL, completionHandler: { (data: NSData?, response: NSURLResponse?, error: NSError?) in

            if let sessionError = error
            {
                print("Error Downloading Image")
                print(sessionError.localizedDescription)
            }
            else if let sessionData = data
            {
                dispatch_async(dispatch_get_main_queue(), {

                    self.currentUser.profileImage = UIImage(data: sessionData)!
                })
            }
        }).resume()
    }
}

Swift 3

func retrieveUserData()
{
    databaseRootRef!.child("path").observeSingleEvent(
    of: .value) { (snapshot: FIRDataSnapshot) in

        if let firebaseValue = snapshot.value as? [String:AnyObject]
        {
            self.currentUser.profileImageURL = firebaseValue["profileImageURL"] as! String
        }

        let imageURL: URL = URL(string: self.currentUser.profileImageURL)!

        URLSession.shared.dataTask(with: imageURL, completionHandler: { (data: Data?, response: URLResponse?, error: Error?) in

            if let sessionError = error
            {
                print("Error downloading image")
                print(sessionError.localizedDescription)
            }
            else if let sessionData = data
            {
                DispatchQueue.main.async(execute: {
                    self.currentUser.profileImage = UIImage(data: sessionData)!
                })
            }

        }).resume()
    }
}

EDIT

  1. FirebaseStorage no longer allows you to add files directly into the root so it's advisable to create directories instead to store your images in. For unique purposes, your image names can be of format var imageName: String = NSUUID().UUIDString + ".png" or you could do what I did which was var imageName: String = userUID + ".png".

  2. Before uploading, its advisable to compress your images first for faster queries and retrievals.

Comments