1

I have an app where a user takes some pictures which are saved into an array, then when he presses a button i want the array of images to be saved to firebase. I have searched around and not found any good resources for this. Bellow is the code I have already written.

DataModel where I save the array of images:

import Foundation
import UIKit

class PhotoArray {
    static let sharedInstance = PhotoArray()
    var photosArray: [UIImage] = []
}

Taking picture code:

import UIKit
import RealmSwift

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    // var realm: Realm!
//    var photoArray = [PhotoArray]()

    @IBOutlet weak var imageView: UIImageView!

    let imagePicker = UIImagePickerController()

    override func viewDidLoad() {
        super.viewDidLoad()
        // realm = try! Realm()
        imagePicker.delegate = self
        imagePicker.sourceType = .camera
        imagePicker.allowsEditing = false
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

        if let userPickedImage = info[UIImagePickerControllerOriginalImage] as? UIImage {

//            let imageToUse = PhotoArray()

//            let data = UIImagePNGRepresentation(userPickedImage) //here convert to data

            PhotoArray.sharedInstance.photosArray.append(userPickedImage)  //append converted data in array

            //                do {
            //                    try realm.write {
            //                        realm.add(imageToUse)
            //                    }
            //                } catch {
            //                    print(“error adding image to array\(error)“)
            //                }

            imageView.image = userPickedImage
        }
//        print(PhotoArray().photosArray.count)
        imagePicker.dismiss(animated: true, completion: nil)
    }

    @IBAction func cameraButtonPressed(_ sender: UIButton) {
        present(imagePicker, animated: true, completion: nil)
    }

@IBAction func cameraButtonPressed(_ sender: UIButton) {
    present(imagePicker, animated: true, completion: nil)
}

@IBAction func SendDataPressed(_ sender: UIButton) {
    //TODO: Send the Images to Firebase and save it in our database

    let messagesDB = Database.database().reference().child("Images")

    let messageDictionary = ["Images": PhotoArray.sharedInstance.photosArray as NSArray]

    messagesDB.childByAutoId().setValue(messageDictionary) {
        (error, refrence) in

        if error != nil {
            print(error!)
            //somthing
        }
        else {
            print("message saved succesfully")
            //somthing
        }
    }

}

}
J. Hoe
  • 53
  • 1
  • 10
  • 1
    Firebase Database is generally not a good solution to store the actual image. You would leverage Storage for the image and store the URL to that storage in Firebase Database. That being said, if it's a small thumbnail, it could be stored in Firebase database. The other issue is using Array's with Firebase; the bottom line is.. don't. Create a node with childByAutoId and store the image or url within that. You didn't include any Firebase code (I only see Realm code) so it's unclear where you are stuck writing to Firebase. Can you clarify your question and include you Firebase code? – Jay Aug 15 '18 at 17:10
  • I added the firebase code – J. Hoe Aug 15 '18 at 17:32
  • You would want to get each image from the array and store them in separate child nodes, with a key created with childByAutoId and the value being a String (an encoded image). However, as I mentioned, if they are thumbnails you get get away with it but for anything more you need to use Storage. Natish has a dandy answer that should help storing in Storage. If they are thumbnails, see my comment to his answer. – Jay Aug 15 '18 at 18:03

1 Answers1

2

Firebase databases don't support adding images to the database. You can find the supported Firebase data types here.

You should instead upload your images to a storage provider such as Firebase Cloud Storage and then save the url to that file in your database to download from later.

Here's an example:

//Create a reference to the image
let imageRef = Storage.storage().reference().child("image.jpg")

// Get image data
if let uploadData = UIImagePNGRepresentation(userPickedImage) {

    // Upload image to Firebase Cloud Storage
    imageRef.putData(uploadData, metadata: nil) { (metadata, error) in
        guard error == nil else {
            // Handle error
            return
        }
        // Get full image url
        imageRef.downloadURL { (url, error) in
            guard let downloadURL = url else {
                // Handle error
                return
            }

            // Save url to database
            Firestore.firestore().collection("images").document("myImage").setData(["imageUrl" : downloadUrl.absoluteString])
        }
    }
}
Nitish K.
  • 391
  • 2
  • 6
  • Good answer but you can certainly store images in Firebase, small thumbnails are ok but anything larger exceeds the capacity of a a child value. See [Images in Firebase](https://stackoverflow.com/questions/33644560/swift2-retrieving-images-from-firebase/34044446#34044446) for an example I did a couple years ago. – Jay Aug 15 '18 at 18:00
  • You're right, I made the assumption that they were trying to store larger size images. If someone is trying to store small images then storing it as encoded data in the database is another good alternative. – Nitish K. Aug 15 '18 at 18:42
  • Hey I am getting unresolved identifier 'Storage' warning/error, is this from firebase or do I need to create it? – J. Hoe Aug 15 '18 at 19:20
  • You need to add the Firebase Storage pod as such: ```pod 'Firebase/Storage'``` – Nitish K. Aug 15 '18 at 19:44
  • I get the following error/warning next to one of the closures: Initializer for conditional binding must have Optional type, not '(@escaping (URL?, Error?) -> Void) -> Void'------this happens at "if let downloadUrl" – J. Hoe Aug 15 '18 at 21:41
  • Updated the example with the fix. – Nitish K. Aug 15 '18 at 21:49
  • Fix the spelling of DownloadURL in the // Save url to database and the answer is perfect. P.S. The code has no errors but then when I run it and see if it works I get a error:======= 2018-08-15 18:17:56.894098-0400 Yubi[2466:1417368] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Yubi.ViewController SendDataPressed:]: unrecognized selector sent to instance 0x117e6cd60' With a quit long terminal message... Shoudl I mark as corrcet or does this mean teh answer is not full? And shoudl I mak ea new question regarding the long output? – J. Hoe Aug 15 '18 at 22:28
  • @J.Hoe That error is in your original code and unrelated to this answer. It's probably because one of the buttons *@IBAction func SendDataPressed* was not hooked up in IB or maybe it list it's link to the function call. – Jay Aug 16 '18 at 17:02
  • ya I fixed it. thaks – J. Hoe Aug 16 '18 at 17:28