【问题标题】:UITableview loads data from Firebase and duplicate rowsUITableview 从 Firebase 加载数据并重复行
【发布时间】:2017-03-30 17:14:45
【问题描述】:

我正在尝试构建一个从 firebase-database 加载数据的应用程序。

将成员保存到 Firebase 没有任何问题。将成员从 Firebase 加载到我的 UITableView 正在工作,然后我对成员进行排序,并根据名字首字母(在 iOS 联系人应用程序中看到的 A、B、C 等)分别在部分标题下添加成员,这可以作为好吧,但是我的 问题 在我加载了所有用户之后发生,例如转到选项卡 1,然后切换回成员选项卡,所有显示的成员/单元格都是重复的。如果我重复相同的过程来回切换选项卡,所有单元格都会重复三次,然后继续。

我已经搜索了不同的来源以寻找解决方案,但我找不到任何类似的东西。

有谁知道解决方案或我做错了什么?

谢谢!

我的视图控制器:

import Foundation
import UIKit

class MembersTableViewController: UITableViewController {

var FBref = FIRDatabaseReference()

var members: [Member] = []
var membersDict = [String: [String]]()
var memberSectionTitles = [String]()

// TODO: Implement user.
//var user: AdminUser!
let fakeuservariable = "fakeuser"

@IBOutlet var memberListTableView: UITableView!


override func viewDidLoad() {
    super.viewDidLoad()

}

override func viewDidAppear(_ animated: Bool) {
    loadDataFromFirebase()
    createFirstnameDict()

}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()

}

// MARK: - Table view data source

override func numberOfSections(in tableView: UITableView) -> Int {

    return memberSectionTitles.count

}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    let firstLetterKey = memberSectionTitles[section]
    if let firstnameValues = membersDict[firstLetterKey] {

        return firstnameValues.count
    }
    return 0

}

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {

    return memberSectionTitles[section]

}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "membercell", for: indexPath)

    let firstLetterKey = memberSectionTitles[indexPath.section]
    if let firstnameValues = membersDict[firstLetterKey] {

        cell.textLabel?.text = firstnameValues[indexPath.row]

    // Not working
    //let memberDetails = members[indexPath.row]
    //cell.detailTextLabel!.text = "Amount left: \(memberDetails.memberamount)"

    }

    return cell

}

func createFirstnameDict() {

    for firstname in members {

        var firstLetter = firstname.firstname

        let firstnameKey = firstLetter.substring(to: firstLetter.characters.index(firstLetter.startIndex, offsetBy: 1))
        if var memberValues = membersDict[firstnameKey] {
            memberValues.append(firstLetter)
            membersDict[firstnameKey] = memberValues
        } else {
            membersDict[firstnameKey] = [firstLetter]

        }

    }

    memberSectionTitles = [String](membersDict.keys)
    memberSectionTitles = memberSectionTitles.sorted { $0 < $1 }

}

func loadDataFromFirebase() {

    let FBref = FIRDatabase.database().reference()
    FBref.child("member-list").observeSingleEvent(of: .value, with: { (snapshot) in
        var resultItem: [Member] = []
        for item in snapshot.children {
            let memberItem = Member(snapshot: item as! FIRDataSnapshot)
            resultItem.append(memberItem)

        }

        self.members = resultItem

        self.createFirstnameDict()

        self.tableView.reloadData()


    }) { (error) in

        print(error.localizedDescription)

    }

}

}

我的会员模型:

import Foundation

struct Member {

let firstname: String
let lastname: String
let email: String
let phonenumber: String
let socialsecuritynr: String
let memberamount: String
let addedByUser: String
let key: String
let ref: FIRDatabaseReference?

init(firstname: String, lastname: String, email: String, phonenumber: String, socialsecuritynr: String, memberamount: String, addedByUser: String, key: String = "") {
    self.key = key
    self.firstname = firstname
    self.lastname = lastname
    self.email = email
    self.phonenumber = phonenumber
    self.socialsecuritynr = socialsecuritynr
    self.memberamount = memberamount
    self.addedByUser = addedByUser
    self.ref = nil

}

init(snapshot: FIRDataSnapshot) {
    key = snapshot.key
    let snapshotValue = snapshot.value as! [String: AnyObject]
    firstname = snapshotValue["firstname"] as! String
    lastname = snapshotValue["lastname"] as! String
    email = snapshotValue["email"] as! String
    phonenumber = snapshotValue["phonenumber"] as! String
    socialsecuritynr = snapshotValue["socialsecuritynr"] as! String
    memberamount = snapshotValue["memberamount"] as! String
    addedByUser = snapshotValue["addedByUser"] as! String
    ref = snapshot.ref
}

func toAnyObject() -> Any {
    return ["firstname": firstname, "lastname": lastname, "email": email, "phonenumber": phonenumber, "socialsecuritynr": socialsecuritynr, "memberamount":memberamount, "addedByUser": addedByUser]

}

}

这是我之前和之后的 TableView:

【问题讨论】:

  • 您是否删除或分离了 EventListner?如果没有,请将其删除以不获取重复项
  • @Muhammad Farrukh Faizy 我不确定你的意思是什么?

标签: ios swift uitableview firebase firebase-realtime-database


【解决方案1】:

问题是由于放置了加载 viewDidAppear 中错误数据的方法:

loadDataFromFirebase()
createFirstnameDict()

这意味着每次您的视图出现时,您的数据都会一次又一次地加载。要解决此问题,请将这些方法移至 viewDidLoad 中,您将不会遇到重复问题。所以你现在应该有:

override func viewDidLoad() {
    super.viewDidLoad()

    loadDataFromFirebase()
    createFirstnameDict()
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)

}

【讨论】:

  • 我可能遗漏了一些东西,但您的回答似乎不能解决我的问题。如果我按照您的建议进行操作,那么 createFirstnameDict() 只会运行一次。当我在应用程序运行时添加新数据时,tableView 不会使用新数据更新或在我的表视图中对用户进行排序。即使我在添加新用户后只运行 tableView.reloadData() 本身,它也不会在没有 createFirstnameDict() 的情况下添加到我的表视图中,所以我相信我在这个函数中做错了什么,这有意义吗?跨度>
  • 然后将您的方法保留在 viewDidAppear 中,但在加载数据之前清空数组和字典。
【解决方案2】:

我建议您清除在之前的事件侦听器中填充的所有数组。这样,您可以确保当它从另一个视图返回时,它不会有旧数据。像这样的:

self.members.removeAll()

【讨论】:

    【解决方案3】:

    您正在 cell.textlabel 中显示来自 membersDict 的数据。 每次加载视图(切换标签时)时,它都会调用 loadDataFromFirebase()

    在这里,所有值都会再次加载并附加到您的 membersValues 中,然后您将其存储在 membersDict 中。

    不会创建 membersDict 的新实例,因为您没有在 viewDidLoad() 中声明它们。您已经在类内但在任何函数之外声明了它们。

    append 的作用是在数组末尾添加一个元素。它不会覆盖元素。因此,如果您有一个包含两个名称的数组,附加一个名称将使您的第三个名称成为您的第三个名称,并且不会覆盖任何现有名称。

    每次加载视图时,都会将名称附加到已包含名称的数组中。这就是导致重复的原因。

    尝试打印您的 membersDictmembersValues 的值,以检查您是否重复。

    您可以通过在本地声明一个 membersDict 实例来解决此问题,这样每次都会创建一个空变量并使用它来显示数据。

    希望这会有所帮助。

    【讨论】:

      【解决方案4】:

      根据我的理解和经验,您在

      中加载 firebase 数据
       override func viewDidLoad() {
          super.viewDidLoad()
          loadFirebaseData()
          }
      

      当您返回到任何其他视图控制器时,您从任何其他视图控制器新创建的数据将出现在您的表上,因为您的观察者仍在侦听,除非您告诉他们在移动到其他视图时停止侦听。

      因此,只要 Firebase 中出现新数据,您的表格就会自动显示它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-10-15
        • 2019-02-13
        • 1970-01-01
        • 2023-03-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多