Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios UITableview从Firebase和重复行加载数据_Ios_Swift_Uitableview_Firebase_Firebase Realtime Database - Fatal编程技术网

Ios UITableview从Firebase和重复行加载数据

Ios UITableview从Firebase和重复行加载数据,ios,swift,uitableview,firebase,firebase-realtime-database,Ios,Swift,Uitableview,Firebase,Firebase Realtime Database,我正在尝试构建一个从firebase数据库加载数据的应用程序 将成员保存到Firebase工作正常,没有任何问题。将成员从Firebase加载到myUITableView正在工作,然后我正在对成员进行排序,并根据名字和首字母(iOS联系人应用程序中的A、B、C等)在节标题下分别添加成员这也可以正常工作,但是在我加载所有用户后出现问题,例如转到选项卡1,然后切换回“成员”选项卡所有显示的成员/单元格都被复制。如果我重复同样的步骤,来回切换标签,所有的单元格都会重复三次,并且会继续 我已经从不同的渠

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

将成员保存到Firebase工作正常,没有任何问题。将成员从Firebase加载到my
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]

}

}
这是我之前和之后的桌面视图:

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]

}

}

问题源于加载数据的方法的位置,这些数据在ViewDidDisplay中出现错误:

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

override func viewDidLoad() {
    super.viewDidLoad()

    loadDataFromFirebase()
    createFirstnameDict()
}

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

}

我建议您清除在事件前侦听器上填充的所有数组。通过这种方式,您可以确保当它从另一个视图返回时,不会有旧数据。大概是这样的:

self.members.removeAll()

您正在单元格中显示来自成员ICT的数据。textlabel。 每次加载视图(切换选项卡时),它都会调用loadDataFromFirebase()

在这里,再次加载所有值并将其附加到成员值中,然后将其存储在membersDict

由于未在viewDidLoad()中声明成员ICT的新实例,因此不会创建该实例。您已在类内但在任何函数外声明了它们

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

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

尝试打印您的成员ICT成员值的值,以检查您是否正在复制

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


希望这有帮助

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

 override func viewDidLoad() {
    super.viewDidLoad()
    loadFirebaseData()
    }
当您返回到表时,您从任何其他视图控制器新创建的数据将显示在表上,因为您的观察者仍在侦听,除非您告诉他们在移动到其他视图时停止侦听


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

您是否删除或分离了EventListner?如果没有,请将其卸下,以避免损坏duplicates@MuhammadFarrukh Faizy我不知道你的意思是什么?我可能遗漏了一些东西,但你的回答似乎并不能解决我的问题。如果我按照您的建议执行,那么数据和createFirstnameDict()将只运行一次。当我在应用程序运行时添加新数据时,tableView不会使用新数据更新,也不会在我的table view中对用户进行排序。即使我只在添加新用户后运行tableView.reloadData()本身,在没有createFirstnameDict()的情况下,它也不会添加到我的表视图中,因此我认为我在该函数中做了一些错误,这有意义吗?然后将方法保留在ViewDidDisplay中,但在加载数据之前清空数组和字典。