Ios UITableview从Firebase和重复行加载数据
我正在尝试构建一个从firebase数据库加载数据的应用程序 将成员保存到Firebase工作正常,没有任何问题。将成员从Firebase加载到myIos 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,然后切换回“成员”选项卡所有显示的成员/单元格都被复制。如果我重复同样的步骤,来回切换标签,所有的单元格都会重复三次,并且会继续 我已经从不同的渠
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中,但在加载数据之前清空数组和字典。