Douglas
Douglas

Reputation: 65

How would I upload new photo into collectionView cell using Firebase?

The code here allows me to upload and download one photo to Firebase and save it to user defaults but I'm trying to figure out how to do it within a collectionView cell and display as many photos wanted, adding on new items

    import UIKit
    import FirebaseStorage
    
        class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
        
            private let storage = Storage.storage().reference()
            
            @IBOutlet var imageView: UIImageView!
            @IBOutlet var label: UILabel!
            
        override func viewDidLoad() {
                super.viewDidLoad()
                // Do any additional setup after loading the view.
                label.numberOfLines = 0
                guard let urlString = UserDefaults.standard.value(forKey: "url") as? String, let url = URL(string: urlString) else {
                    return
                }
                label.text = urlString
                let task = URLSession.shared.dataTask(with: url, completionHandler: { data,_,error in
                    guard let data = data, error == nil else {
                        return
                }
                DispatchQueue.main.async {
                    let image = UIImage(data: data)
                    self.imageView.image = image
                    }
            })
                task.resume()
        }
            @IBAction func didTapButton() {
                let picker = UIImagePickerController()
                picker.sourceType = .photoLibrary
                picker.delegate = self
                picker.allowsEditing = true
                present(picker, animated: true, completion: nil)
            }
            func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
                picker.dismiss(animated: true, completion: nil)
                guard let image = info[UIImagePickerController.InfoKey.editedImage] as? UIImage else {
                    return
                }
                guard let imageData = image.pngData() else {
                    return
                }
                storage.child("Images/Photo.png").putData(imageData, metadata: nil) { (_, error) in
                    guard error == nil else {
                        print("Failed to Upload Data")
                        return
                    }
                    self.storage.child("Images/Photo.png").downloadURL(completion: {url, error in
                        guard let url = url, error == nil else {
                            return
                        }
                        let urlString = url.absoluteString
                        DispatchQueue.main.async {
                            self.label.text = urlString
                            self.imageView.image = image
                        }
                        print("Download URL: \(urlString)")
                        UserDefaults.standard.set(urlString, forKey: "url")
                    })
                }
                // Upload Image Data
                // Get Download URL
                // Save Download URL to userDefaults
            }
            func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
                picker.dismiss(animated: true, completion: nil)
            }
        }

Upvotes: 2

Views: 522

Answers (1)

Jithin
Jithin

Reputation: 943

To upload images to Firebase storage and show them in a collection view, you can use the following steps;

  1. Set up collection view with an array of URLs (or Strings) as its data source. You can use your custom models if required.

  2. Keep a reference to your Firebase storage and upload the image. After successful upload, get the URL for the uploaded image using the image reference.

  3. Save the url in Firebase Database(or Cloud Firestore). This is required only if you want to sync the collection view with the database and update it when new images are uploaded.

  4. Add a listener to your Firebase database reference where you have saved the image URLs. Update the local URLs array inside the listener and reload the collection view.

If you don't want to use Firebase database, omit steps 3 and 4, save the image URL to the array and reload the collection view right away.

I'm not adding the code for collection view setup here as it's not the objective of this answer.

let storageRef = Storage.storage().reference(withPath: "images")
let databaseRef = Database.database().reference(withPath:"images")
var images: [String] = []

override func viewDidLoad() {
    super.viewDidLoad()
    
    addDatabaseListener()
}

private func addDatabaseListener() {
    databaseRef.observe(.childAdded) { (snapshot) in
        
        guard let value = snapshot.value as? [String: Any], let url = value["url"] as? String else { return }
        self.images.append(url)
        DispatchQueue.main.async {
            self.collectionView.reloadData()
        }
    }
}


func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
    picker.dismiss(animated: true)
    guard let image = info[UIImagePickerController.InfoKey.editedImage] as? UIImage, let data = image.jpegData(compressionQuality: 0.1) else { return }

    let fileName = "\(Date.timeIntervalSinceReferenceDate).jpeg"
    let newImageRef = storageRef.child(fileName)
    
    newImageRef.putData(data, metadata: nil) { (_, error) in
        if let error = error {
            print("upload failed: ", error.localizedDescription)
            return
        }
        
        newImageRef.downloadURL { (url, error) in
            if let error = error {
                print("error: ", error.localizedDescription)
                return
            }
            self.databaseRef.childByAutoId().setValue(["url": url?.absoluteString])
        }
    }
    
}

Upvotes: 1

Related Questions