草庐IT

ios - Swift Firestore - 从 Firestore 中删除表格单元格和删除文档

coder 2023-09-10 原文

我正在使用 Swift 开发一个育儿应用程序,我正在使用 Firebase Cloud Firestore 为我的 Swift 应用程序保存数据。应用程序的一部分是 parent 可以添加他们的 child 并在应用程序中显示他们的地方。

我创建了一个子模型,我在将新子模型添加到我的 tableview 时使用它。

child 模型

protocol DocumentSerializable {
    init?(dictionary:[String:Any])
}

// Child Struct
struct Child {

    var name: String
    var age: Int
    var timestamp: Date
    var imageURL: String

    var dictionary:[String:Any] {
        return [
            "name":name,
            "age":age,
            "timestamp":timestamp,
            "imageURL":imageURL
        ]
    }

}

//Child Extension
extension Child : DocumentSerializable {
    init?(dictionary: [String : Any]) {
        guard let  name = dictionary["name"] as? String,
            let age = dictionary["age"] as? Int,
            let  imageURL = dictionary["imageURL"] as? String,
            let timestamp = dictionary["timestamp"] as? Date else {
                return nil
        }
        self.init(name: name, age: age, timestamp: timestamp, imageURL: imageURL)
    }
}

我通过在我的 View 中运行一个函数加载数据,将数据添加到我的应用程序中的 TableView ,loadData()

我首先在上面设置了 2 个变量:

//firestore connection
var db:Firestore!

//child array
var childArray = [Child]()

viewDidLoad

override func viewDidLoad() {
    super.viewDidLoad()

    //Connect to database
    db = Firestore.firestore()

    // call load data function
    loadData()
    checkForUpdates()

}

loadData() 函数连接到已登录的用户数据,然后获取用户的“ child ”文档并使用子对象协议(protocol)将 child 添加到 childArray。

func loadData() {
        // create ref to generate a document ID
        let user = Auth.auth().currentUser
        db.collection("users").document((user?.uid)!).collection("children").getDocuments() {
            QuerySnapshot, error in
            if let error = error {
                print("\(error.localizedDescription)")
            } else {
                // get all children into an array
                self.childArray = QuerySnapshot!.documents.flatMap({Child(dictionary: $0.data())})
                DispatchQueue.main.async {
                    self.childrenTableView.reloadData()
                }
            }
        }
    }

我通过像这样返回 childArray 计数来获得 numberOfRowsInSection:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return childArray.count
    }

我使用自定义单元格类填充 cellForRow 并使用 childArray 内容,如下所示:

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
       let cell = childrenTableView.dequeueReusableCell(withIdentifier: "Cell") as! ChildCellTableViewCell
        let child = childArray[indexPath.row]

        cell.childNameLabel.text = "\(child.name)"
        cell.childAgeLabel.text =  "Age: \(child.age)"

        let url = URL(string: "\(child.imageURL)")
        cell.childImage.kf.setImage(with: url)

        cell.childNameLabel.textColor = UIColor.white
        cell.childAgeLabel.textColor = UIColor.white
        cell.backgroundColor = UIColor.clear

        return cell
    }

我希望能够通过滑动来删除每个表格行单元格,所以我实现了以下内容:

 func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        return true
    }

    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        if (editingStyle == UITableViewCellEditingStyle.delete) {

            childArray.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: .fade)

        }
    }

这成功地从应用程序中删除了该行。但我的问题是我不确定如何获取已删除的行以从 Firestore 数据库中删除匹配数据。

更复杂的是,由于每个 child 都有一张存储在 Firebase 存储中的图像,我还需要以某种方式删除该图像。图片 URL 存储在 imageURL 下的子文档中。

我将不胜感激任何指导或为此指出正确的方向,我找不到太多关于 Firestore 和 UITableViews 的文档,所以不知道下一步该尝试什么?


更新'canEditRow' 函数中,我设法从我删除的表行中的 Firebase 存储中删除了子图像,但我正在努力从 Firestore 中删除子文档。我可以查询我需要删除的文档,但不确定如何从此查询运行 delete() 函数?

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        if (editingStyle == UITableViewCellEditingStyle.delete) {

            // 1. First Delete the childs image from storage
            let storage = Storage.storage()
            let childsImageURL = childArray[indexPath.row].imageURL
            let storageRef = storage.reference(forURL: childsImageURL)

            storageRef.delete { error in
                if let error = error {
                    print(error.localizedDescription)
                } else {
                    print("File deleted successfully")
                }
            }


            // 2. Now Delete the Child from the database
            let name = childArray[indexPath.row].name

            let user = Auth.auth().currentUser
            let query = db.collection("users").document((user?.uid)!).collection("children").whereField("name", isEqualTo: name)

            print(query)


            childArray.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: .fade)

        }
    }

最佳答案

我想我已经设法解决了这个问题,而且它似乎正在发挥作用。在 'canEditRow' 函数中,编号 2,我现在可以找到特定的子项(当滑动表格单元格以删除时),它会在 Firebase Firestore 数据库中删除相同的子项。

我不确定这是否是正确的做法,或者我是否遗漏了任何错误检查,但一切似乎都正常。

如果有人在这里发现任何错误,请告诉我,我真的很想确保它可以安全使用并且所有后备措施都已到位。

所以这就是我为使整个事情顺利进行所做的工作。

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        if (editingStyle == UITableViewCellEditingStyle.delete) {

            // 1. First Delete the childs image from storage
            let storage = Storage.storage()
            let childsImageURL = childArray[indexPath.row].imageURL
            let storageRef = storage.reference(forURL: childsImageURL)

            storageRef.delete { error in
                if let error = error {
                    print(error.localizedDescription)
                } else {
                    print("File deleted successfully")
                }
            }



            // 2. Now Delete the Child from the database
            let name = childArray[indexPath.row].name
            let user = Auth.auth().currentUser
            let collectionReference = db.collection("users").document((user?.uid)!).collection("children")
            let query : Query = collectionReference.whereField("name", isEqualTo: name)
            query.getDocuments(completion: { (snapshot, error) in
                if let error = error {
                    print(error.localizedDescription)
                } else {
                    for document in snapshot!.documents {
                        //print("\(document.documentID) => \(document.data())")
                        self.db.collection("users").document((user?.uid)!).collection("children").document("\(document.documentID)").delete()
                }
            }})


            // 3. Now remove from TableView
            childArray.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: .fade)

        }
    }

关于ios - Swift Firestore - 从 Firestore 中删除表格单元格和删除文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47480661/

有关ios - Swift Firestore - 从 Firestore 中删除表格单元格和删除文档的更多相关文章

  1. ruby-on-rails - 如何从 format.xml 中删除 <hash></hash> - 2

    我有一个对象has_many应呈现为xml的子对象。这不是问题。我的问题是我创建了一个Hash包含此数据,就像解析器需要它一样。但是rails自动将整个文件包含在.........我需要摆脱type="array"和我该如何处理?我没有在文档中找到任何内容。 最佳答案 我遇到了同样的问题;这是我的XML:我在用这个:entries.to_xml将散列数据转换为XML,但这会将条目的数据包装到中所以我修改了:entries.to_xml(root:"Contacts")但这仍然将转换后的XML包装在“联系人”中,将我的XML代码修改为

  2. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

    查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

  3. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  4. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  5. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  6. ruby - 如何安全地删除文件? - 2

    在Ruby中是否有Gem或安全删除文件的方法?我想避免系统上可能不存在的外部程序。“安全删除”指的是覆盖文件内容。 最佳答案 如果您使用的是*nix,一个很好的方法是使用exec/open3/open4调用shred:`shred-fxuz#{filename}`http://www.gnu.org/s/coreutils/manual/html_node/shred-invocation.html检查这个类似的帖子:Writingafileshredderinpythonorruby?

  7. ruby-on-rails - Prawn - 表格单元格内的链接 - 2

    我正在尝试用Prawn生成PDF。在我的PDF模板中,我有带单元格的表格。在其中一个单元格中,我有一个电子邮件地址:cell_email=pdf.make_cell(:content=>booking.user_email,:border_width=>0)我想让电子邮件链接到“mailto”链接。我知道我可以这样链接:pdf.formatted_text([{:text=>booking.user_email,:link=>"mailto:#{booking.user_email}"}])但是将这两行组合起来(将格式化文本作为内容)不起作用:cell_email=pdf.make_c

  8. ruby-on-rails - 标准化文件名的字符串,删除重音和特殊字符 - 2

    我正在尝试找到一种方法来规范化字符串以将其作为文件名传递。到目前为止我有这个:my_string.mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n,'').downcase.gsub(/[^a-z]/,'_')但第一个问题:-字符。我猜这个方法还有更多问题。我不控制名称,名称字符串可以有重音符、空格和特殊字符。我想删除所有这些,用相应的字母('é'=>'e')替换重音符号,并将其余的替换为'_'字符。名字是这样的:“Prélèvements-常规”“健康证”...我希望它们像一个没有空格/特殊字符的文件名:“prelevements_routin

  9. Matlab imread()读到了什么 (浅显 当复习文档了) - 2

    matlab打开matlab,用最简单的imread方法读取一个图像clcclearimg_h=imread('hua.jpg');返回一个数组(矩阵),往往是a*b*cunit8类型解释一下这个三维数组的意思,行数、数和层数,unit8:指数据类型,无符号八位整形,可理解为0~2^8的数三个层数分别代表RGB三个通道图像rgb最常用的是24-位实现方法,即RGB每个通道有256色阶(2^8)。基于这样的24-位RGB模型的色彩空间可以表现256×256×256≈1670万色当imshow传入了一个二维数组,它将以灰度方式绘制;可以把图像拆分为rgb三层,可以以灰度的方式观察它figure(1

  10. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

随机推荐