How to delete a child from Firebase (Swift)

12,591

Solution 1

This should work.

func deletePost() {
  let uid = FIRAuth.auth()!.currentUser!.uid
  let storage = FIRStorage.storage().reference(forURL: "gs://cloudcamerattt.appspot.com")

  // Remove the post from the DB
  ref.child("posts").child(selectedPost.postID).removeValue { error in
    if error != nil {
        print("error \(error)")
    }
  }
  // Remove the image from storage
  let imageRef = storage.child("posts").child(uid).child("\(selectedPost.postID).jpg")
  imageRef.delete { error in
    if let error = error {
      // Uh-oh, an error occurred!
    } else {
     // File deleted successfully
    }
  }
}

Also .childByAutoId().key generates a key to insert items into the DB. You can't use it get a reference to an existing item.

Solution 2

According to Firebase docs, you can also delete it by

specifying null as the value for another write operation such as set() or update()

You can use this technique with update() to delete multiple children in a single API call.

Share:
12,591

Related videos on Youtube

KingTim
Author by

KingTim

Updated on June 04, 2022

Comments

  • KingTim
    KingTim almost 2 years

    I've been following a tutorial on making an instragram-esque app, and I'm having a lot of trouble figuring out how to delete a post, both from Firebase and from the feed. The image that the user selects or takes is uploaded to Firebase database with this function:

    func uploadToFirebase() {
        AppDelegate.instance().showActivityIndicator()
    
        let uid = FIRAuth.auth()!.currentUser!.uid
        let ref = FIRDatabase.database().reference()
        let storage = FIRStorage.storage().reference(forURL: "gs://cloudcamerattt.appspot.com")
    
        let key = ref.child("posts").childByAutoId().key
        let imageRef = storage.child("posts").child(uid).child("\(key).jpg")
    
        let data = UIImageJPEGRepresentation(self.previewImage.image!, 0.6)
    
        let uploadTask = imageRef.put(data!, metadata: nil) { (metadata, error) in
    
            if error != nil {
                print(error!.localizedDescription)
                AppDelegate.instance().dismissActivityIndicator()
                return
            }
    
            imageRef.downloadURL(completion: { (url, error) in
    
                if let url = url {
                    // how do I add date: NSDate in here?
                    let feed = ["userID" : uid,
                                "pathToImage" : url.absoluteString,
                                "likes" : 0,
                                "author" : FIRAuth.auth()!.currentUser!.displayName!,
                                "postID" : key] as [String : Any]
    
                    let postFeed = ["\(key)" : feed]
    
                    ref.child("posts").updateChildValues(postFeed)
                    AppDelegate.instance().dismissActivityIndicator()
    
                    self.dismiss(animated: true, completion: nil)
                }
            })
        }
        uploadTask.resume()
    }
    

    Which ends up in Firebase looking like this:

    enter image description here

    Following a stack overflow answer I found, I tried to set up a delete function to be called when the delete button is pressed. This delete button is on a "photo detail" view, which the user gets to by tapping an image in the image feed - this photo detail view displays the image in a bigger size, along with some other info such as likes:

    func deletePost(firstTree: String, childIWantToRemove: String) {
    
        let uid = FIRAuth.auth()!.currentUser!.uid
        let ref = FIRDatabase.database().reference()
        let storage = FIRStorage.storage().reference(forURL: "gs://cloudcamerattt.appspot.com")
    
        let key = ref.child("posts").childByAutoId().key
        let imageRef = storage.child("posts").child(uid).child("\(key).jpg")
    
        ref.child("posts").child(key).child("postID").removeValue { (error, ref) in
            if error != nil {
                print("error \(error)")
            }
        }
    }
    

    And call the function here:

    @IBAction func moreButtonPressed(_ sender: AnyObject) {
    
        let alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
        let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
        let destroyAction = UIAlertAction(title: "Delete", style: .destructive) { action in
            print(action)
    
            let ref = FIRDatabase.database().reference()
            let key = ref.child("posts").childByAutoId().key
    
            let firstTree = key
            let valueToRemove = "postID"
            self.deletePost(firstTree: firstTree, childIWantToRemove: valueToRemove)
        }
    
        alertController.addAction(destroyAction)
        alertController.addAction(cancelAction)
        self.present(alertController, animated: true)
    }
    

    I'm not really understanding what I'm doing though, and needless to say tapping the delete button does essentially nothing. Can anyone show me how to fix the delete function so I can remove an image/post from firebase properly?

    EDIT: I have var selectedPost: Post! in my PhotoDetailController, which is passed from the FeedViewController (image feed) in didSelectItem like so:

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let photoDetailController = self.storyboard?.instantiateViewController(withIdentifier: "photoDetail") as! PhotoDetailController
    
        photoDetailController.selectedPost = posts[indexPath.row]
    
        present(photoDetailController, animated: true, completion: nil)
    }
    

    So it has the index path. Another note about the above function is that var posts = [Post]() is instantiated in the FeedViewController, so that's where posts[indexPath.row] comes from.

    • Admin
      Admin about 7 years
      Do you have a post object in your detailView with the info of the current post in the detail view? Or any object that contains the information of the post (such as the ID)?
    • KingTim
      KingTim about 7 years
      Hey Pieter yes I have a variable which holds the Post object and the index path of the selected image from the feed - check my edit, I put the code there to make it clearer.
  • KingTim
    KingTim about 7 years
    Thank you so much! It worked perfectly. Looking at your code, this actually ended up being more straightforward than I thought, I was getting wrapped up in trying to figure out how to use the childByAutoID. Thanks again much appreciated!