简体   繁体   中英

Index Out of Range when deleting from TableView?

Just as a heads up I am using Firebase to store/remove data.

Here is my viewDidLoad code:

 override func viewDidLoad()
{
    super.viewDidLoad()

    observePeople()

    tableView.delegate = self
    tableView.dataSource = self

}

The observePeople() method operates like this (I reload the table twice here)

 func observePeople()
{
    let ref = FIRDatabase.database().reference().child("Users")
    ref.observeEventType(.ChildAdded, withBlock:
    { (snapshot) in

        if let firstname = snapshot.value?.objectForKey("firstname"), lastname = snapshot.value?.objectForKey("lastname")
        {
            let fullname = "\(firstname) \(lastname)"
            self.names.append(fullname)

            dispatch_async(dispatch_get_main_queue())
            {
                self.tableView.reloadData()
            }
        }

    }, withCancelBlock: nil)

    ref.observeEventType(.ChildRemoved, withBlock:
    { (snapshot) in

    if let firstname = snapshot.value?.objectForKey("firstname"), lastname = snapshot.value?.objectForKey("lastname"), dateOfBirth = snapshot.value?.objectForKey("Date of Birth"), zipcode = snapshot.value?.objectForKey("Zipcode")
    {
        print("We deleted the person \(firstname) \(lastname) with the details: \(dateOfBirth), \(zipcode)")
        self.tableView.reloadData()
    }

    }, withCancelBlock: nil)
}

And in my viewDidAppear I refresh the table again:

override func viewDidAppear(animated: Bool)
{
    tableView.reloadData()
}

Lastly, I once I delete the row I get the error saying the index is out of range. What is interesting is when I populate my table with 4 items, if I delete the first item it'll ACTUALLY delete the second item, and if i delete the third one it'll actually delete the fourth one, and so on. I've been adding breakpoints to observe this phenomenon the best I can and it breaks right after I remove it from the tableview.

override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)
{
    if editingStyle == .Delete
    {
        let ref = FIRDatabase.database().reference().child("Users")
        ref.observeEventType(.ChildAdded, withBlock: { (snapshot) in

            if let firstname = snapshot.value?.objectForKey("firstname"), lastname = snapshot.value?.objectForKey("lastname")
            {
                let fullname = "\(firstname) \(lastname)"
                let currentName = self.names[indexPath.row]

                if fullname == currentName
                {
                    print("We have a match")
                    let currentKey = snapshot.key
                    ref.child(currentKey).removeValue()

                    dispatch_async(dispatch_get_main_queue())
                    {
                        self.tableView.reloadData()
                    }
                }

            }

            }, withCancelBlock: nil)
    }

        names.removeAtIndex(indexPath.row)
        tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
    }
}

So right after the tableView.deleteRows method I'm getting the error. Been at this for a while and can't seem to locate it. Also, I always make sure the arrays match up for the database and the array so they're both empty at the same time before I populate them.

Working with firebase changes how you generally work with tables. You may think you have to delete from the array and then delete the rows from the tableView because thats what we do with array data for most cases, but in doing so it causes problems when firebase is querying or listening. The best way to handle this is not to delete any data from arrays or the table manually in the commitEditingStyle function. Instead only remove the value from firebase. Then in your listener for .ChildRemoved remove the object from the array of data and reload the table.

Delete

  names.removeAtIndex(indexPath.row)
  tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)

And Insert the removal of the name in your .ChildRemoved listener

ref.observeEventType(.ChildRemoved, withBlock:
{ (snapshot) in

if let firstname = snapshot.value?.objectForKey("firstname"), lastname = snapshot.value?.objectForKey("lastname"), dateOfBirth = snapshot.value?.objectForKey("Date of Birth"), zipcode = snapshot.value?.objectForKey("Zipcode")
{
    print("We deleted the person \(firstname) \(lastname) with the details: \(dateOfBirth), \(zipcode)")
    let fullname = "\(firstname) \(lastname)"
    if let index = names.indexOf(fullname) {
       names.removeAtIndex(index)
       self.tableView.reloadData()
    }
}

}, withCancelBlock: nil)

i think you have to move these lines before you despatch

    names.removeAtIndex(indexPath.row)
    tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM