javarookie
javarookie

Reputation: 59

Index Out of Range When Deleting From Firebase and UITableView

I currently have a problem that when I try to delete a row from a table, my app crashes and throws an index out of range error. The data deletes fine from the firebase database and the table, but it still throws the error.

The database is designed to store playlists, and each playlist has a dictionary of keys to the name of the song. Here is my firebase structure:enter image description here

And below is the swift code (line where error is occurring has a comment)

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    let song = songs[indexPath.row]
    var songKey = ""
    if(editingStyle == .delete){
        let ref = Database.database().reference().child("Playlists/\(playlist!)")
        ref.observe(.value, with: {
            snapshot in
            let someData = snapshot.value! as! [String: String]
            for data in someData {
                if(data.value == song){
                    songKey = data.key
                    break
                }
            }
            ref.child(songKey).removeValue()
            self.songs.remove(at: indexPath.row) //error on this line
            self.myTableView.deleteRows(at: [indexPath], with: .fade)
            self.myTableView.reloadData()
        })
    }
}

Thanks for any help!

Upvotes: 0

Views: 129

Answers (1)

Vasil Garov
Vasil Garov

Reputation: 4921

I think what you should do is take another approach - handle the delete operation within its completion handler. This way you will make sure your data will be consistent. Because what happens if there is an error on your Firebase call? You have to handle this case as well. So do something like this and see what happens:

ref.child(songKey).removeValue { [weak self] error, _ in 
    if let error = error {
        print("There was an error: ", error)
        return
    }
    self?.songs.remove(at: indexPath.row)
    self?.tableView.reloadData()
}

What I think is happening here is that your code enters an infinite loop - you use observe on your playlists then you delete. So observe's completion handler is called again and delete is called again. After you deleted the item at this index, the index cannot be found on your array anymore. So just get your playlists from the database without observing any further changes.

In this case try using observeSingleEvent.

Upvotes: 1

Related Questions