Ios 从Firebase删除后,Swift 3 UITableView未更新

Ios 从Firebase删除后,Swift 3 UITableView未更新,ios,uitableview,firebase,swift3,Ios,Uitableview,Firebase,Swift3,当用户在UITableView上滑动以删除时,我试图从Firebase数据库中删除项目 我还使用了中的漂亮的showActivityIndicator和hideActivityIndicator函数,以便轻松显示和隐藏活动指示器 运行以下代码时,我可以看到数据库记录以及从Firebase中正确删除的JPG文件 但问题是,活动指示器永远不会从屏幕上消失,UITableView也不会刷新 事实上 print("Stopping activity indicator") 及 甚至不要跑 我做错了什么

当用户在UITableView上滑动以删除时,我试图从Firebase数据库中删除项目

我还使用了中的漂亮的showActivityIndicator和hideActivityIndicator函数,以便轻松显示和隐藏活动指示器

运行以下代码时,我可以看到数据库记录以及从Firebase中正确删除的JPG文件

但问题是,活动指示器永远不会从屏幕上消失,UITableView也不会刷新

事实上

print("Stopping activity indicator")

甚至不要跑

我做错了什么

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)
        }
    }

您需要在块内部编写代码,如下所示:

 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()
                    }
                }

您需要在块内部编写代码,如下所示:

 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()
                    }
                }

仍然不确定Firebase removeValue和delete函数下面的代码为什么没有运行,但我设法找到了一个解决方法

事实证明,只有当我删除表上最后一条剩余记录时,代码才起作用,之后整个Firebase节点都被删除

因此,我添加了一个观察者,以便在发生这种情况时强制重新加载表

在viewDidLoad()下,我添加了以下行:

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
}

仍然不确定Firebase removeValue和delete函数下面的代码为什么没有运行,但我设法找到了一个解决方法

事实证明,只有当我删除表上最后一条剩余记录时,代码才起作用,之后整个Firebase节点都被删除

因此,我添加了一个观察者,以便在发生这种情况时强制重新加载表

在viewDidLoad()下,我添加了以下行:

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
}

要使tableView和Firebase保持同步,有两个主要选项:

1) 从Firebase中删除节点时,请手动将其从 从Firebase中删除tableView数据源时。不需要观察员

2) 将移除事件观察者连接到Firebase,以便在移除节点时, 你的应用程序将收到它所在节点的事件,并将其删除

这里有一个例子;为了简洁起见,我省略了tableView代码

假设我们有一个显示用户的tableView。tableView有一个usersArray数据源,其中包含UserClass对象

给定一个火基结构

users
  user_0
    name: "Frank"
  user_2
    name: "Bill"
  user_3
    name: "Hugh"
我们向用户节点添加了三个观察者: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
    }
})
如果添加了用户,.childAdded observer将接收新用户,以便将其追加到数组中

如果用户已更改,.childChanged观察者将接收更改的用户。抓取密钥(通常是uid),在数组中找到它并更新属性

如果删除了用户,.childRemoved observer将接收删除的用户。抓取密钥,在数组中找到它并将其移除


在每种情况下,在更改数据源后重新加载tableView。

要使tableView和Firebase保持同步,有两个主要选项:

1) 从Firebase中删除节点时,请手动将其从 从Firebase中删除tableView数据源时。不需要观察员

2) 将移除事件观察者连接到Firebase,以便在移除节点时, 你的应用程序将收到它所在节点的事件,并将其删除

这里有一个例子;为了简洁起见,我省略了tableView代码

假设我们有一个显示用户的tableView。tableView有一个usersArray数据源,其中包含UserClass对象

给定一个火基结构

users
  user_0
    name: "Frank"
  user_2
    name: "Bill"
  user_3
    name: "Hugh"
我们向用户节点添加了三个观察者: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
    }
})
如果添加了用户,.childAdded observer将接收新用户,以便将其追加到数组中

如果用户已更改,.childChanged观察者将接收更改的用户。抓取密钥(通常是uid),在数组中找到它并更新属性

如果删除了用户,.childRemoved observer将接收删除的用户。抓取密钥,在数组中找到它并将其移除


在每种情况下,在更改数据源后重新加载tableView。

不,这仍然不起作用。活动指示器仍然显示,并且该项目在表视图上仍然可见。控制台上显示“照片已成功删除”和“重新加载表视图”消息,但活动指示器没有消失。我已经尝试删除showActivityIndicator和hideActivityIndicator,但现在表视图只是放在那里,没有删除行。有点,但我认为它“太快”了。我认为重新加载是在Firebase数据库条目被完全删除之前触发的,因此重新加载仍然会尝试从数据库中提取数据。如果我调度一个队列以异步删除数据库项和照片,可能效果会更好?不,它不会在数据库删除之前触发,因为在删除过程完成时块被调用。不,这仍然不起作用。活动指示器仍然显示,并且该项目在表视图上仍然可见。控制台上显示“照片已成功删除”和“重新加载表视图”消息,但活动指示器没有消失。我已经尝试删除showActivityIndicator和hideActivityIndicator,但现在表视图只是放在那里,没有删除行。有点,但我认为它“太快”了。我认为重新加载是在Firebase数据库条目被完全删除之前触发的,因此重新加载仍然会尝试从数据库中提取数据。如果我调度一个队列以异步删除数据库项和照片,可能效果会更好?不,它不会在数据库删除之前触发,因为在删除过程完成时会调用块。部分问题是Firebase是异步的。removeValue闭包后面的代码在从Firebase中移除项之前执行。还有一点不清楚是什么repairItem,repairItem.imageRef,以及预期的结果