UITableview从Firebase和重复行加载数据

时间:2016-11-16 13:22:22

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

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

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

我搜索了不同来源的解决方案,但我找不到任何相似的内容。

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

谢谢!

我的Viewcontroller:

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:

TableView before and after

4 个答案:

答案 0 :(得分:1)

问题来自于放置加载viewDidAppear中错误数据的方法:

loadDataFromFirebase()
createFirstnameDict()

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

override func viewDidLoad() {
    super.viewDidLoad()

    loadDataFromFirebase()
    createFirstnameDict()
}

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

}

答案 1 :(得分:0)

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

self.members.removeAll()

答案 2 :(得分:0)

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

此处,所有值都会再次加载并附加到 membersValues ,然后存储在 membersDict 中。

由于您未在 viewDidLoad()中声明它们,因此无法创建 membersDict 的新实例。你已经在类中声明了它们,但在任何函数之外。

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

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

尝试打印 membersDict membersValues 的值,以检查是否重复。

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

希望这会有所帮助。

答案 3 :(得分:0)

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

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

当您返回到桌面时,来自任何其他视图控制器的新创建的数据将显示在您的桌面上,因为除非您在移动到其他视图时告诉他们停止收听,否则您的观察者仍在监听。

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