Swift 在未显示的表视图上显示 firebase 数据
Swift display firebase data on tableview not shown
我正在使用 firebase 作为数据库制作应用程序,但我似乎无法将我的数据显示到我的表格视图中。我检查我的 firebase 我的所有数据都很好,即使我添加新数据数据也会立即显示在我的 firebase 中。但似乎我这里有些逻辑错误....有人可以帮助我吗?
*编辑有 1 行代码不起作用
这是我的主控制器:
class MainController: UITableViewController, AddPatientControllerr {
private var patientLists = [PatientList]()
var Segue : String = "PatientName"
var Segue2 : String = "PatientNotes"
let user : User = Auth.auth().currentUser!
private var rootRef : DatabaseReference!// 1. buat nyambung ke root db
override func viewDidLoad() {
super.viewDidLoad()
self.rootRef = Database.database().reference()
populateList()
tableView.delegate = self
tableView.dataSource = self
}
// MARK : Firebase Function
private func populateList() {
self.rootRef.child(self.user.emailWithoutSpecialChar).observe(.value) { (snapshot) in
self.patientLists.removeAll()
let pasienListDict = snapshot.value as? [String:Any] ?? [:]
for (key,_) in pasienListDict {
if let pasienlistdict = pasienListDict[key] as? [String:Any]{
if let pasienlist = PatientList(pasienlistdict) { // this line of code is not working
self.patientLists.append(pasienlist)
}else {
print("your condition not working")
}
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
// MARK : Func delegate
func addPatientData(controller: UIViewController, nama: String, tglLahir: String, Telp: String, berat: String, Tinggi: String, golDarah: String) {
let patientList = PatientList(name: nama, tglLahir: tglLahir, Telp: Telp, berat: berat, Tinggi: Tinggi, golDarah: golDarah)
self.patientLists.append(patientList)
let userRef = self.rootRef.child(self.user.emailWithoutSpecialChar)
let patientListRef = userRef.child(patientList.name)
patientListRef.setValue(patientList.toDictionary())
controller.dismiss(animated: true, completion: nil)
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
// MARK : Segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == Segue {
let nc = segue.destination as! UINavigationController
let addPatientName = nc.viewControllers.first as! ProfileController
addPatientName.delegate = self
}
else if segue.identifier == Segue2 {
guard let indexPath = self.tableView.indexPathForSelectedRow else {return}
let nc = segue.destination as! PasienProfileController
nc.pasien = self.patientLists[indexPath.row]
}
}
//MARK : TableView
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
let pasienList = self.patientLists[indexPath.row]
let pasienListRef = self.rootRef.child(pasienList.name)
pasienListRef.removeValue()
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.patientLists.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as? MainCell else {return UITableViewCell()}
let patientListt = self.patientLists[indexPath.row]
cell.NameLbl.text = patientListt.name
return cell
}
}
这是我保存数据和字典的模型:
import Foundation
typealias JSONDictionary = [String:Any]
class PatientList {
var name : String!
var tglLahir : String!
var Telp : String!
var berat : String!
var Tinggi : String!
var golDarah : String!
var patientNote :[PatientNote] = [PatientNote]() //ini buat nyimpen notes2 dari tiap2 pasien
init(name : String, tglLahir : String, Telp : String, berat : String, Tinggi : String, golDarah : String) {
self.name = name
self.tglLahir = tglLahir
self.berat = berat
self.Tinggi = Tinggi
self.golDarah = golDarah
self.Telp = Telp
}
init?(_ dictionary :[String:Any]){
guard let name = dictionary["Name"] as? String else {
return nil
}
guard let berat = dictionary["BeratBadan"] as? String else {
return nil
}
guard let tglLahir = dictionary["TanggalLahir"] as? String else {
return nil
}
guard let Tinggi = dictionary["TinggiBadan"] as? String else {
return nil
}
guard let golDarah = dictionary["GolonganDarah"] as? String else {
return nil
}
guard let Telp = dictionary["Telefon"] as? String else {
return nil
}
self.name = name
self.berat = berat
self.tglLahir = tglLahir
self.Tinggi = Tinggi
self.golDarah = golDarah
self.Telp = Telp
let pasienListDictionary = dictionary["patientNote"] as? [JSONDictionary]
if let dictionaries = pasienListDictionary {
self.patientNote = dictionaries.compactMap(PatientNote.init)
}
}
func toDictionary() -> [String:Any] { // ini buat dictionary buat convery object jd string:any, jd biar ga ngubah satu2 kl ada yg salah gituu
return ["Name":self.name, "BeratBadan":self.berat, "TanggalLahir":self.tglLahir, "TinggiBadan":self.Tinggi, "golDarah":self.golDarah, "Telefon":self.Telp, "patientNote":self.patientNote.map{ patientNote in
return patientNote.toDictionary()
}]
}
}
这是我的 firebase :
[![Firebase][1]][1]
对于初学者,我只需要在我的表格视图中显示我的名字,在这种情况下,我什至无法在我的表格视图中显示姓名数据
我似乎无法找出为什么数据不会显示在我的表格视图中....xcode 未显示错误
有人可以帮助我吗?谢谢
firebase Json
"afipermanalivecom" : {
"Apiyyy" : {
"BeratBadan" : "",
"Name" : "Apiyyy",
"TanggalLahir" : "20-05-2020",
"Telefon" : "",
"TinggiBadan" : "",
"golDarah" : "A+"
},
"CocaCola" : {
"BeratBadan" : "80",
"Name" : "CocaCola",
"TanggalLahir" : "20-06-2020",
"Telefon" : "0878099996049",
"TinggiBadan" : "190",
"golDarah" : "A-"
},
"Jamsey" : {
"BeratBadan" : "",
"Name" : "Jamsey",
"TanggalLahir" : "19-06-2020",
"Telefon" : "",
"TinggiBadan" : "",
"golDarah" : "A-"
}
},
"puffygmailcom" : {
"Batman" : {
"Name" : "Batman"
},
"Stitchh" : {
"Name" : "Stitchh"
}
}
只是一些提示,也许还有一个解决方案,
我建议使用 firebase Cloud 而不是 firebase 实时 firebase,它更快更可靠,尤其是当您尝试从数组或字典中查询数据时,我可以看到您正在尝试从字典中检索数据,这是您要注意的一件事是 firebase 将您的 swift 字典存储为 objective C 字典,所以这是您要注意的一件事!尝试检查您是否使用了正确的重用标识符。
如果您仍然无法获取,请告诉我!
如果您想 return 数据列表,则必须使用 .childAdded
而不是 .value
所以,您的代码应该是这样的:
self.rootRef.child(self.user.emailWithoutSpecialChar).observe(.childAdded) { (snapshot) in
// do your stuff here
}
*salam sesama orang 印度尼西亚 :)
从问题中的代码和结构来看,有一个医生和患者列表,其中患者是医生的子节点。我将 post 一个解决方案,然后是一些关于更改的重要建议。
这是现有的 Firebase 结构。请注意,我们没有使用电子邮件地址作为节点键——这是很多额外的工作,如果电子邮件地址发生变化,整个数据库将被扫描,节点被读取、删除和重写。应该使用 .childByAutoId 生成动态节点密钥(可以更改的密钥,如电子邮件)——我使用 doctor_0、doctor_1 等来提高可读性。
{
"doctor_0" : {
"name" : "Dr. Doolittle",
"patient_list" : {
"patient_0" : {
"blood_type" : "O-",
"name" : "Henry"
},
"patient_1" : {
"blood_type" : "AB-",
"name" : "Leroy"
}
}
},
"doctor_1" : {
"name" : "Dr. McCoy",
"patient_list" : {
"patient_2" : {
"blood_type" : "O+",
"name" : "Steve"
}
}
}
}
我有两个 class 保存此数据,DoctorClass 和 PatientClass,其中 Patient class 是 DoctorClass 中的一个数组。请注意,医生可能没有任何患者,因此我将其视为可选项。
class DoctorClass {
var doc_id = ""
var doc_name = ""
var patients = [PatientClass]()
convenience init(withId: String, andName: String, maybePatientList: DataSnapshot?) {
self.init()
self.doc_id = withId
self.doc_name = andName
if let patientList = maybePatientList {
let allPatientsSnap = patientList.children.allObjects as! [DataSnapshot]
for patientSnap in allPatientsSnap {
let patient = PatientClass(patientSnap: patientSnap)
self.patients.append(patient)
}
}
}
}
class PatientClass {
var patient_id = ""
var patient_name = ""
var blood_type = ""
convenience init(patientSnap: DataSnapshot) {
self.init()
self.patient_id = patientSnap.key
self.patient_name = patientSnap.childSnapshot(forPath: "name").value as? String ?? "No Name"
self.blood_type = patientSnap.childSnapshot(forPath: "blood_type").value as? String ?? "No blood type"
}
}
最后是读取所有医生并用患者填充患者数组的代码。
var docAndPatientList = [DoctorClass]()
func loadDoctorsAndPatients() {
let doctorsRef = self.ref.child("doctors") //self.ref points to *my* firebase
doctorsRef.observeSingleEvent(of: .value, with: { snapshot in
let allDoctorsSnapshot = snapshot.children.allObjects as! [DataSnapshot]
for docSnap in allDoctorsSnapshot {
let docId = docSnap.key
let docName = docSnap.childSnapshot(forPath: "name").value as? String ?? ""
let patientSnap = docSnap.childSnapshot(forPath: "patient_list")
let doc = DoctorClass(withId: docId, andName: docName, maybePatientList: patientSnap)
self.docAndPatientList.append(doc)
}
})
}
然后打印出来
func printDoctorsAndPatients() {
self.docAndPatientList.forEach { doctor in
print("Dr: \(doctor.doc_name)")
for patient in doctor.patients {
print(" patient: \(patient.patient_name) bloodtype: \(patient.blood_type)")
}
}
}
和输出
Dr: Dr. Doolittle
patient: Henry bloodtype: O-
patient: Leroy bloodtype: AB-
Dr: Dr. McCoy
patient: Steve bloodtype: O+
这将适用于现有结构,但是如果例如一位患者有两位医生怎么办?或者,如果我们想在 Firebase 中查询所有 O 型血的患者怎么办?它不会(轻松地)使用该结构。
这是一个更好的计划
root_ref
doctors
doctor_0
name : "Dr. Doolittle"
patients
patient_0 : true
patient_1 : true
doctor_1
name : "Dr. McCoy"
patients
patient_2 : true
和患者
root_ref
patients
patient_0
blood_type : "O-"
doctors:
doctor_0: true
name : "Henry"
patient_1
blood_type : "AB-"
doctors:
doctor_0: true
name : "Leroy"
patient_2
blood_type : "O+"
doctors:
doctor_1: true
name : "Steve"
这种结构提供了更多的查询灵活性和可扩展性。
我正在使用 firebase 作为数据库制作应用程序,但我似乎无法将我的数据显示到我的表格视图中。我检查我的 firebase 我的所有数据都很好,即使我添加新数据数据也会立即显示在我的 firebase 中。但似乎我这里有些逻辑错误....有人可以帮助我吗?
*编辑有 1 行代码不起作用
这是我的主控制器:
class MainController: UITableViewController, AddPatientControllerr {
private var patientLists = [PatientList]()
var Segue : String = "PatientName"
var Segue2 : String = "PatientNotes"
let user : User = Auth.auth().currentUser!
private var rootRef : DatabaseReference!// 1. buat nyambung ke root db
override func viewDidLoad() {
super.viewDidLoad()
self.rootRef = Database.database().reference()
populateList()
tableView.delegate = self
tableView.dataSource = self
}
// MARK : Firebase Function
private func populateList() {
self.rootRef.child(self.user.emailWithoutSpecialChar).observe(.value) { (snapshot) in
self.patientLists.removeAll()
let pasienListDict = snapshot.value as? [String:Any] ?? [:]
for (key,_) in pasienListDict {
if let pasienlistdict = pasienListDict[key] as? [String:Any]{
if let pasienlist = PatientList(pasienlistdict) { // this line of code is not working
self.patientLists.append(pasienlist)
}else {
print("your condition not working")
}
}
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
// MARK : Func delegate
func addPatientData(controller: UIViewController, nama: String, tglLahir: String, Telp: String, berat: String, Tinggi: String, golDarah: String) {
let patientList = PatientList(name: nama, tglLahir: tglLahir, Telp: Telp, berat: berat, Tinggi: Tinggi, golDarah: golDarah)
self.patientLists.append(patientList)
let userRef = self.rootRef.child(self.user.emailWithoutSpecialChar)
let patientListRef = userRef.child(patientList.name)
patientListRef.setValue(patientList.toDictionary())
controller.dismiss(animated: true, completion: nil)
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
// MARK : Segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == Segue {
let nc = segue.destination as! UINavigationController
let addPatientName = nc.viewControllers.first as! ProfileController
addPatientName.delegate = self
}
else if segue.identifier == Segue2 {
guard let indexPath = self.tableView.indexPathForSelectedRow else {return}
let nc = segue.destination as! PasienProfileController
nc.pasien = self.patientLists[indexPath.row]
}
}
//MARK : TableView
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
let pasienList = self.patientLists[indexPath.row]
let pasienListRef = self.rootRef.child(pasienList.name)
pasienListRef.removeValue()
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.patientLists.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as? MainCell else {return UITableViewCell()}
let patientListt = self.patientLists[indexPath.row]
cell.NameLbl.text = patientListt.name
return cell
}
}
这是我保存数据和字典的模型:
import Foundation
typealias JSONDictionary = [String:Any]
class PatientList {
var name : String!
var tglLahir : String!
var Telp : String!
var berat : String!
var Tinggi : String!
var golDarah : String!
var patientNote :[PatientNote] = [PatientNote]() //ini buat nyimpen notes2 dari tiap2 pasien
init(name : String, tglLahir : String, Telp : String, berat : String, Tinggi : String, golDarah : String) {
self.name = name
self.tglLahir = tglLahir
self.berat = berat
self.Tinggi = Tinggi
self.golDarah = golDarah
self.Telp = Telp
}
init?(_ dictionary :[String:Any]){
guard let name = dictionary["Name"] as? String else {
return nil
}
guard let berat = dictionary["BeratBadan"] as? String else {
return nil
}
guard let tglLahir = dictionary["TanggalLahir"] as? String else {
return nil
}
guard let Tinggi = dictionary["TinggiBadan"] as? String else {
return nil
}
guard let golDarah = dictionary["GolonganDarah"] as? String else {
return nil
}
guard let Telp = dictionary["Telefon"] as? String else {
return nil
}
self.name = name
self.berat = berat
self.tglLahir = tglLahir
self.Tinggi = Tinggi
self.golDarah = golDarah
self.Telp = Telp
let pasienListDictionary = dictionary["patientNote"] as? [JSONDictionary]
if let dictionaries = pasienListDictionary {
self.patientNote = dictionaries.compactMap(PatientNote.init)
}
}
func toDictionary() -> [String:Any] { // ini buat dictionary buat convery object jd string:any, jd biar ga ngubah satu2 kl ada yg salah gituu
return ["Name":self.name, "BeratBadan":self.berat, "TanggalLahir":self.tglLahir, "TinggiBadan":self.Tinggi, "golDarah":self.golDarah, "Telefon":self.Telp, "patientNote":self.patientNote.map{ patientNote in
return patientNote.toDictionary()
}]
}
}
这是我的 firebase :
[![Firebase][1]][1]
对于初学者,我只需要在我的表格视图中显示我的名字,在这种情况下,我什至无法在我的表格视图中显示姓名数据
我似乎无法找出为什么数据不会显示在我的表格视图中....xcode 未显示错误
有人可以帮助我吗?谢谢
firebase Json
"afipermanalivecom" : {
"Apiyyy" : {
"BeratBadan" : "",
"Name" : "Apiyyy",
"TanggalLahir" : "20-05-2020",
"Telefon" : "",
"TinggiBadan" : "",
"golDarah" : "A+"
},
"CocaCola" : {
"BeratBadan" : "80",
"Name" : "CocaCola",
"TanggalLahir" : "20-06-2020",
"Telefon" : "0878099996049",
"TinggiBadan" : "190",
"golDarah" : "A-"
},
"Jamsey" : {
"BeratBadan" : "",
"Name" : "Jamsey",
"TanggalLahir" : "19-06-2020",
"Telefon" : "",
"TinggiBadan" : "",
"golDarah" : "A-"
}
},
"puffygmailcom" : {
"Batman" : {
"Name" : "Batman"
},
"Stitchh" : {
"Name" : "Stitchh"
}
}
只是一些提示,也许还有一个解决方案, 我建议使用 firebase Cloud 而不是 firebase 实时 firebase,它更快更可靠,尤其是当您尝试从数组或字典中查询数据时,我可以看到您正在尝试从字典中检索数据,这是您要注意的一件事是 firebase 将您的 swift 字典存储为 objective C 字典,所以这是您要注意的一件事!尝试检查您是否使用了正确的重用标识符。
如果您仍然无法获取,请告诉我!
如果您想 return 数据列表,则必须使用 .childAdded
而不是 .value
所以,您的代码应该是这样的:
self.rootRef.child(self.user.emailWithoutSpecialChar).observe(.childAdded) { (snapshot) in
// do your stuff here
}
*salam sesama orang 印度尼西亚 :)
从问题中的代码和结构来看,有一个医生和患者列表,其中患者是医生的子节点。我将 post 一个解决方案,然后是一些关于更改的重要建议。
这是现有的 Firebase 结构。请注意,我们没有使用电子邮件地址作为节点键——这是很多额外的工作,如果电子邮件地址发生变化,整个数据库将被扫描,节点被读取、删除和重写。应该使用 .childByAutoId 生成动态节点密钥(可以更改的密钥,如电子邮件)——我使用 doctor_0、doctor_1 等来提高可读性。
{
"doctor_0" : {
"name" : "Dr. Doolittle",
"patient_list" : {
"patient_0" : {
"blood_type" : "O-",
"name" : "Henry"
},
"patient_1" : {
"blood_type" : "AB-",
"name" : "Leroy"
}
}
},
"doctor_1" : {
"name" : "Dr. McCoy",
"patient_list" : {
"patient_2" : {
"blood_type" : "O+",
"name" : "Steve"
}
}
}
}
我有两个 class 保存此数据,DoctorClass 和 PatientClass,其中 Patient class 是 DoctorClass 中的一个数组。请注意,医生可能没有任何患者,因此我将其视为可选项。
class DoctorClass {
var doc_id = ""
var doc_name = ""
var patients = [PatientClass]()
convenience init(withId: String, andName: String, maybePatientList: DataSnapshot?) {
self.init()
self.doc_id = withId
self.doc_name = andName
if let patientList = maybePatientList {
let allPatientsSnap = patientList.children.allObjects as! [DataSnapshot]
for patientSnap in allPatientsSnap {
let patient = PatientClass(patientSnap: patientSnap)
self.patients.append(patient)
}
}
}
}
class PatientClass {
var patient_id = ""
var patient_name = ""
var blood_type = ""
convenience init(patientSnap: DataSnapshot) {
self.init()
self.patient_id = patientSnap.key
self.patient_name = patientSnap.childSnapshot(forPath: "name").value as? String ?? "No Name"
self.blood_type = patientSnap.childSnapshot(forPath: "blood_type").value as? String ?? "No blood type"
}
}
最后是读取所有医生并用患者填充患者数组的代码。
var docAndPatientList = [DoctorClass]()
func loadDoctorsAndPatients() {
let doctorsRef = self.ref.child("doctors") //self.ref points to *my* firebase
doctorsRef.observeSingleEvent(of: .value, with: { snapshot in
let allDoctorsSnapshot = snapshot.children.allObjects as! [DataSnapshot]
for docSnap in allDoctorsSnapshot {
let docId = docSnap.key
let docName = docSnap.childSnapshot(forPath: "name").value as? String ?? ""
let patientSnap = docSnap.childSnapshot(forPath: "patient_list")
let doc = DoctorClass(withId: docId, andName: docName, maybePatientList: patientSnap)
self.docAndPatientList.append(doc)
}
})
}
然后打印出来
func printDoctorsAndPatients() {
self.docAndPatientList.forEach { doctor in
print("Dr: \(doctor.doc_name)")
for patient in doctor.patients {
print(" patient: \(patient.patient_name) bloodtype: \(patient.blood_type)")
}
}
}
和输出
Dr: Dr. Doolittle
patient: Henry bloodtype: O-
patient: Leroy bloodtype: AB-
Dr: Dr. McCoy
patient: Steve bloodtype: O+
这将适用于现有结构,但是如果例如一位患者有两位医生怎么办?或者,如果我们想在 Firebase 中查询所有 O 型血的患者怎么办?它不会(轻松地)使用该结构。
这是一个更好的计划
root_ref
doctors
doctor_0
name : "Dr. Doolittle"
patients
patient_0 : true
patient_1 : true
doctor_1
name : "Dr. McCoy"
patients
patient_2 : true
和患者
root_ref
patients
patient_0
blood_type : "O-"
doctors:
doctor_0: true
name : "Henry"
patient_1
blood_type : "AB-"
doctors:
doctor_0: true
name : "Leroy"
patient_2
blood_type : "O+"
doctors:
doctor_1: true
name : "Steve"
这种结构提供了更多的查询灵活性和可扩展性。