Riccardo
Riccardo

Reputation: 299

Firebase Upload Images and getting URL issue

I am trying to take 3 images and post it in firebase storage and get a download URL and put it in the Firebase Database. My code only uploads the first image but won't upload anything if there is a second.

@IBOutlet weak var titleText: UITextField!
@IBOutlet weak var subtitleText: UITextField!
@IBOutlet weak var authorText: UITextField!
@IBOutlet weak var dateText: UITextField!
@IBOutlet weak var articleText: UITextView!
@IBOutlet weak var tagsText: UITextField!
@IBOutlet weak var myImageView1: UIImageView!
@IBOutlet weak var myImageView2: UIImageView!
@IBOutlet weak var myImageView3: UIImageView!
@IBOutlet weak var postType: UITextField!
@IBOutlet weak var postStyle: UITextField!

var ref:DatabaseReference?

override func viewDidLoad() {

    super.viewDidLoad()  
    ref = Database.database().reference()  

    let tapGestureRecognizer1 = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
    myImageView1.isUserInteractionEnabled = true
    myImageView1.addGestureRecognizer(tapGestureRecognizer1)
    let tapGestureRecognizer2 = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
    myImageView2.isUserInteractionEnabled = true
    myImageView2.addGestureRecognizer(tapGestureRecognizer2)
    let tapGestureRecognizer3 = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
    myImageView3.isUserInteractionEnabled = true
    myImageView3.addGestureRecognizer(tapGestureRecognizer3)        

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

var selected = 0

func imageTapped(tapGestureRecognizer: UITapGestureRecognizer){
    let image = UIImagePickerController()
    image.delegate = self
    image.sourceType = UIImagePickerControllerSourceType.photoLibrary
    image.allowsEditing = false
    let tappedImage = tapGestureRecognizer.view as! UIImageView
    selected = tappedImage.tag
    self.present(image, animated: true)
}

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
    if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
        if let myImageView1 = self.view.viewWithTag(selected) as? UIImageView {
            myImageView1.image = image
        }
    } else {
        //error
    }
    self.dismiss(animated: true, completion: nil)
}

@IBAction func upload(_ sender: Any) {

    let storageRef = Storage.storage().reference().child("images/\(NSUUID().uuidString)/image.png")

    if let uploadData = UIImagePNGRepresentation(self.myImageView1.image!) {

        storageRef.putData(uploadData, metadata: nil, completion: { (metadata, error) in 

            let storageRef2 = Storage.storage().reference().child("images2/\(NSUUID().uuidString)/image2.png")
            if let uploadData2 = UIImagePNGRepresentation(self.myImageView2.image!) {

                storageRef2.putData(uploadData2, metadata: nil, completion: { (metadataSecond, error) in

                    if error != nil {
                        print("error")
                        return              
                    } else {
                        let downloadURL = metadata?.downloadURL()?.absoluteString
                        let downloadURL2 = metadataSecond?.downloadURL()?.absoluteString
                                  self.ref?.child("Posts").childByAutoId().setValue(["Title": self.titleText.text, "Subtitle": self.subtitleText.text, "Article": self.articleText.text, "Author": self.authorText.text, "Date": self.dateText.text, "Tags": self.tagsText.text, "PostType": self.postType.text, "PostStyle": self.postStyle.text, "Download URL": (downloadURL), "Download URL 2": (downloadURL2)])

                    }
                    self.performSegue(withIdentifier: "segue321", sender: self)

}

Upvotes: 0

Views: 614

Answers (2)

DionizB
DionizB

Reputation: 1507

try this for three images at the same time in the beginning of the class you add a counter

var counter: Int = 0

and then you modify imagePickerController: `

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

    if counter == 0{
        if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
            if let myImageView1 = self.view.viewWithTag(selected) as? UIImageView {
                myImageView1.image = image
                counter +=1
            }
        } else {
            //error
        }
      }
      else if counter==1{
          if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
            if let myImageView2 = self.view.viewWithTag(selected) as? UIImageView {
                myImageView2.image = image
                counter+=1
            }
        } else {
            //error
        }
      else{
        if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
          if let myImageView3 = self.view.viewWithTag(selected) as? UIImageView {
            myImageView3.image = image
            counter = 0
        }
    } else {
        //error
    }
    }
    self.dismiss(animated: true, completion: nil)
}

I dont know if it's gonna work for only two images at a time, but for three at a time its gonna work. For other cases you should give it a try yourself!

Upvotes: 0

eshirima
eshirima

Reputation: 3867

If I understood your imageviews, it seems like you have multiple imageviews and for each one the user is able to pick an image from.

With this in mind, your current code handles just one case i.e. myImageView1, but no handling is performed for myImageView2 and myImageView3.

1. Scalable Solution

What you need to do is put your imageviews in an array, then iterate through this array and start uploading each image.

PS: This code isn't tested and is meant to be used as a reference

Create the array holding your imageviews in your viewDidLoad() as shown below

var imageViews: [UIImageView]

override func viewDidLoad() 
{
    // After initializing them 
    imageViews = [myImageView1, myImageView2, myImageView3]
}

Since you have a selected variable that keeps track of the imageView that was tapped, we can use it as well to access the respective views in our array as shown below

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) 
{
    if let image = info[UIImagePickerControllerOriginalImage] as? UIImage
    {
        imageViews[selected].image = image
    } 
    else 
    {
        //error
    }
    self.dismiss(animated: true, completion: nil)
}

In your upload, you want to iterate over imageViews and start uploading each respective image.

@IBAction func upload(_ sender: Any) 
{
    let storageRef = Storage.storage().reference().child("images/\(NSUUID().uuidString)/image.png")

    for imageView in imageViews
    {
        if let uploadData = UIImagePNGRepresentation(imageView.image)
        {
            // continue with your stuff
        }
        else
        {
            // Upload Data creation error
        }
    }
}

2. Non-scalable

Just write multiple if statements in imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) to account for myImageView2 and myImageView3

Two Cents:

I'd recommend the first solution because its not limited by the number of imageviews you currently have. Should you opt to add more in the future, simply append it to the array. The second solution though, leads to multiple if statements and convoluted code.

Edit 1 Bug Discovered

In the above implementation, it assumes that the user will select all the image views in a sequential order i.e. imageView1->imageView2->imageView3->imageView4->imageView5->etc. What if the user selects imageView1->imageView3->imageView5?

Our array will look like this in the above scenario:

[0]->[has image]
[1]->[nil]
[2]->[has image]
[3]->[nil]
[4]->[has image]

The nil segments will result into a crash when trying to create a UIImagePNGRepresentation.

A simple image existence check prior to uploading will resolve this issue.

@IBAction func upload(_ sender: Any) 
{
    let storageRef = Storage.storage().reference().child("images/\(NSUUID().uuidString)/image.png")

    for imageView in imageViews
    {
        if imageView.image != nil
        {
            if let uploadData = UIImagePNGRepresentation(imageView.image)
            {
                // continue with your stuff
            }
            else
            {
                // upload data creation error
            }
        }

    }
}

Upvotes: 1

Related Questions