简体   繁体   中英

Swift 3 UITableView not updating after deleting from Firebase

I'm trying to delete items from a Firebase database when user swipes to delete on the UITableView.

I'm also using the nifty showActivityIndicator and hideActivityIndicator functions from https://github.com/erangaeb/dev-notes/blob/master/swift/ViewControllerUtils.swift in order to easily show and hide the activity indicator.

I can see both the database record as well as the JPG file properly deleted from Firebase when the following code is run.

But the problem is that the activity indicator never disappears from the screen, and the UITableView does not refresh.

In fact, the

print("Stopping activity indicator")

and

print("Reloading table view")

do not even run.

What am I doing wrong?

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            let alert = UIAlertController(title: "Delete Task", message: "Do you want to delete this task?", preferredStyle: .alert)
            let confirmAction = UIAlertAction(title:"OK", style: .default) { action in
                // Show activity indicator
                ViewControllerUtils().showActivityIndicator(uiView: self.view)

                // Retrieve Firebase reference to delete
                let repairItem = self.repairItems[indexPath.row]
                let storage = Storage.storage()
                let storageRef = storage.reference()
                let imageRef = storageRef.child(repairItem.imageRef)

                // Delete the item from Firebase
                repairItem.ref?.removeValue(completionBlock: {(error, ref) in
                    if let error = error {
                        print("Problem deleting item")
                    } else {
                        print("Item deleted successfully")
                    }
                })

                // Delete the photo
                imageRef.delete { error in
                    if let error = error {
                        print("Problem deleting photo")
                    } else {
                        print("Photo deleted successfully")
                    }
                }

                print("Stopping activity indicator")
                // Stop the activity indicator
                ViewControllerUtils().hideActivityIndicator(uiView: self.view)

                print("Reloading table view")
                // Reloading table view
                self.tableView.reloadData()
            }

            let cancelAction = UIAlertAction(title: "Cancel", style: .default)

            alert.addAction(confirmAction)
            alert.addAction(cancelAction)

            present(alert, animated: true, completion: nil)
        }
    }

Still not sure why the code below the Firebase removeValue and delete functions aren't running, but I managed to figure out a workaround.

Turns out that the code doesn't work only when I'm deleting the last remaining record on the table, after which the entire Firebase node is removed.

So I've added an observer to forcefully reload the table when this happens.

Under viewDidLoad(), I added the following lines:

override func viewDidLoad() {
    super.viewDidLoad()

    // ... other preceding lines of code

    // Forcefully trigger a TableView refresh in case the Firebase node is empty
    refItems.observe(.value, with: { snapshot in
        if snapshot.exists() {
            print("Found the Firebase node")
        } else {
            print("Firebase node doesn't exist")
            self.tableView.reloadData()
        }
    })

    // ...other following lines of code
}

When it comes to keeping a tableView and Firebase synchronized, there are two main options:

1) When removing a node from Firebase, manually remove it from the tableView datasource when removing it from Firebase. No observer needed.

2) Attach a remove event observer to Firebase so when a node is removed, your App will receive an event of which node it was, and remove it.

Here's an example; I am leaving the tableView code out for the sake of brevity.

Suppose we have a tableView that displays users. The tableView has a dataSource of usersArray which contain UserClass objects.

Given a Firebase structure

users
  user_0
    name: "Frank"
  user_2
    name: "Bill"
  user_3
    name: "Hugh"

We add three observers to the users node, childAdded, childChanged, childRemoved

class UserClass {
    var key = ""
}

var usersArray = [UserClass]()

let usersRef = self.ref.child("users")

usersRef.observe(.childAdded, with: { snapshot in
    let user = UserClass()
    user.key = snapshot.key
    self.usersArray.append(user)
    self.tableView.reloadData()
})

usersRef.observe(.childChanged, with: { snapshot in
    if let index = self.usersArray.index(where: {$0.key == snapshot.key}) {
        //update it in the array via the index
        self.tableView.reloadData()
    } else {
        //item not found
    }
})

usersRef.observe(.childRemoved, with: { snapshot in
    if let index = self.usersArray.index(where: {$0.key == snapshot.key}) {
        self.usersArray.remove(at: index) //remove it from the array via the index
        self.tableView.reloadUI()
    } else {
        item not found
    }
})

If a user is added, the .childAdded observer receives the new user so it can be appended to the array.

If a user is changed, the .childChanged observer receives the changed user. Grab the key, which would typically be the uid, locate it in the array and update the properties.

If a user is removed, the .childRemoved observer receives the removed user. Grab the key, locate it in the array and remove it.

In each case, reload the tableView after the change to the dataSource.

you need to write code inside of block as below :

 imageRef.delete { error in
                    if let error = error {
                        print("Problem deleting photo")
                    } else {
                        print("Photo deleted successfully")
                      ViewControllerUtils().hideActivityIndicator(uiView: self.view)

                     print("Reloading table view")
                      // Reloading table view
                        self.tableView.reloadData()
                    }
                }

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