处理 UITableView 中的动态单元格?
Dealing with dynamic cells in a UITableView?
New Error Message
Error Message.
现在,我明白了 error message。
已更新代码,此图中显示错误消息 link error message:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = runReportTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = valuesArray[indexPath.row]
cell.SetCheckMark(cell.checkMark) //Call 'SetCheckMark' function here
cell.tapButton = {
if cell.checkMark.isSelected == false {
let data:[String:String] = [self.Facilities[indexPath.row]: "Disinfected"]
self.InfoArray.append(data)
}
else {
self.InfoArray.remove(at: indexPath.row)
}
}
print("Responsibilities in cells: \(valuesArray)")
print("\(data)")
return cell
}
我让这段代码一直运行到“print("You taped cell #(indexPath.row)")”。此代码生成包含某些字段的此 firebase 文档:this document should have fields of the room/area text and values of "Disinfected" or "Not Disinfected" depending on whether the user selected that cell or left it unselected
因此,我现在需要此代码做的就是使用用户 select 编辑的单元格的文本 (valuesArray[indexPath.row]) 更新我的 Cloud Firestore 文档。在我的 viewController 上使用静态数量的按钮和标签之前,我已经完美地工作了,并且在我的 firebase Firestore 文档中得到了我想要的结果,如下所示:screenshot of when I had static information that I was updating in my firebase database after the user made all selections and tapped the "send report" button
但是,现在,我想知道如何在 firebase 文档中使用 selected 值“已消毒”或“未消毒”显示常量“房间 1”-“房间 21”键如果单元格是 selected/highlighted 或如果用户没有 select 单元格,我可以让我的代码自动写入该 firebase 文档“已消毒”,然后显示哪个单元格具有该值disinfected/notdisinfected 使用我从下方“Firestore 文档数据屏幕截图”中的数据中获取的单元格标签文本。
我认为这是因为我不是 100% 确定如何检查我创建的动态单元格是否 selected 或没有然后将“已消毒”或“未消毒”分配给 select在我的 Cloud Firestore 文档中编辑了单元格的文本。
如前所述,此代码打印正确的点击单元格编号和正确的点击单元格标签文本。它还成功创建了一个新的 Cloud Firestore 文档,其中没有 selected 按钮的值(“Disinfected”或“Not Disinfected”)及其匹配的单元格标签文本。
这是模拟器的屏幕截图Simulator Screenshot and a screenshot of the Cloud Firestore document data that I'm using for my cells' label text Firestore Document Data Screenshot。
import UIKit
import Firebase
import FirebaseFirestore
import SCLAlertView
class RunReportViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var runReportTableView: UITableView!
var namesDocumentRef:DocumentReference!
var userName = ""
var userEmail = ""
var data:[String] = []
var valuesArray:[String] = []
var selectedResponsibility:[String] = []
// var keysArray:[String] = []
override func viewDidLoad() {
super.viewDidLoad()
startObservingDB()
runReportTableView.delegate = self
runReportTableView.dataSource = self
// Do any additional setup after loading the view.
}
// Gets user's specific room(s)/area(s)/classroom(s) responsibilities from Cloud Firestore Database to be used for checking "Disinfected" or "Not Disinfected" in order to put the text as a cell label
func startObservingDB() {
var responsibilitiesDocumentRef:DocumentReference!
let db = Firestore.firestore()
let userID = Auth.auth().currentUser!.uid
responsibilitiesDocumentRef = db.collection("UserResponsibilities").document("McGrath").collection("Custodians").document("\(userID)")
responsibilitiesDocumentRef.addSnapshotListener { DocumentSnapshot, error in
if error != nil{
return
}
else {
guard let snapshot = DocumentSnapshot, snapshot.exists else {return}
guard let data = snapshot.data() else { return }
self.valuesArray = Array(data.values) as! Array<String>
// self.keysArray = Array(data.keys)
self.runReportTableView.reloadData()
print("Current data: \(data)")
print("Current data has the responsibilities: \(self.valuesArray)")
print("Current data totals \(self.valuesArray.count) items.")
}
}
}
@IBAction func sendReportTapped(_ sender: Any) {
getSelectionValues()
}
func getSelectionValues() {
let db = Firestore.firestore()
let userID = Auth.auth().currentUser!.uid
db.collection("Users").document("\(userID)").collection("UserInfo").getDocuments { (snapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in snapshot!.documents {
let docID = document.documentID
self.userName = document.get("Name") as! String
self.userEmail = document.get("Email") as! String
print("Current document is: \(docID)")
print("Current user's name: \(self.userName)")
}
db.collection("Run Reports").document("Custodians").collection("Custodians").document("\(String(describing: userID))").collection("Run Reports").document("\(self.getCurrentShortDate())").setData ([
"Name": "\(String(describing: self.userName))",
"Email": "\(String(describing: self.userEmail))",
"Admin": Bool(false),
"Last Updated": FieldValue.serverTimestamp(),
])
}
// getting values of selection code:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("The cell you tapped has the text: \(self.valuesArray[indexPath.row])")
// let selectedResponsibility = "\(self.valuesArray[indexPath.row])"
print("You tapped cell #\(indexPath.row)")
这就是问题所在。这段代码只是我在试验,尽管我更新 firebase 文档的代码有效——“设置责任 1 的状态”有效。它只是不适用于我上面关于动态单元格的信息,这些信息都是实验性的并且是错误的,因为不起作用:
// let currentUsersCellCount = self.valuesArray.count
let cell = self.runReportTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let dynamicCell = self.runReportTableView.cellForRow(at: indexPath)
if dynamicCell?.isSelected == true {
let status = "Disinfected"
let DocumentRef = db.collection("Run Reports").document("Custodians").collection("Custodians").document("\(String(describing: userID))").collection("Run Reports").document("\(self.getCurrentShortDate())")
// Set the status of Responsibility 1
DocumentRef.updateData(["\(self.valuesArray[indexPath.row])" : "\(status)"])
}
else if dynamicCell?.isSelected == false {
let status = "Not Disinfected"
let DocumentRef = db.collection("Run Reports").document("Custodians").collection("Custodians").document("\(String(describing: userID))").collection("Run Reports").document("\(self.getCurrentShortDate())")
// Set the status of Responsibility 1
DocumentRef.updateData(["\(self.valuesArray[indexPath.row])" : "\(status)"])
}
一切正常:
// Setup action for when "Send Report" and alert buttons are tapped
let appearance = SCLAlertView.SCLAppearance(
// Hide default button???
showCloseButton: false
)
// Create alert with appearance
let alert = SCLAlertView(appearance: appearance)
alert.addButton("Done", action: {
// Show SendReportViewController after successfully sent report and alert button is tapped
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "SendReportViewController")
vc.modalPresentationStyle = .overFullScreen
self.present(vc, animated: true)
// create button on alert
print("'Done' button was tapped.")
})
alert.showSuccess("Report Sent!", subTitle: "Your Run Report has been sent to your supervisor.", closeButtonTitle: "Done", timeout: nil, colorStyle: SCLAlertViewStyle.success.defaultColorInt, colorTextButton: 0xFFFFFF, circleIconImage: nil, animationStyle: .topToBottom)
}
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("The cell you tapped has the text: \(valuesArray[indexPath.row])")
// let selectedResponsibility = "\(valuesArray[indexPath.row])"
print("You tapped cell #\(indexPath.row)")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return valuesArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = runReportTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = valuesArray[indexPath.row]
print("Responsibilities in cells: \(valuesArray)")
print("\(data)")
return cell
}
// using date to create new firestore document with date as the title
func getCurrentShortDate() -> String {
let todaysDate = NSDate()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "(MM-dd-yy)"
let DateInFormat = dateFormatter.string(from: todaysDate as Date)
return DateInFormat
}
}
如果您想将有关您在 fireStore 文档中选择的单元格的信息存储为 Text of the cell
:Disinfected
或 Not Disinfected
,即 ConferenceRoom
:Disinfected
,那么这就是我的建议。
首先,在tableViewCell
文件中,添加以下属性
var tapButton: (() -> Void)? = nil //This will allow you to get the text of the row you have selected
然后,我想你的单元格内有一个按钮,在你的情况下它位于左侧,可以点击或取消点击。让我们将该按钮名称称为 checkMark
,这样它就会像这样在您的 tableviewCell
文件中声明。
@IBOutlet weak var checkMark: UIButton!
现在,添加一个函数 SetCheckMark
以便用户可以查看单元格是否已选中。此外,您将需要两个图像,它们将被分配给处于选中或未选中状态的按钮。
@IBAction func SetCheckMark(_ sender: UIButton) {
//If button is selected, then
if checkMark.isSelected == true {
checkMark.setImage(UIImage(named: "Check"), for: .normal)
checkMark.isSelected = false
}
else {
checkMark.setImage(UIImage(named: "UnCheck"), for: .normal)
checkMark.isSelected = true
}
tapButton?() //This is the property that we declared above.
}
现在,你差不多完成了。进入你的主文件。首先在File开头添加一个字典来保存信息。
var InfoArray:[[String:String]] = [["":""]]
现在,在您的 tableView cellForRowAt indexPath: IndexPath
函数中,添加这些行。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = runReportTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.label.text = valuesArray[indexPath.row]
cell.SetCheckMark(cell.checkMark) //Call `SetCheckmark` function here
cell.tapButton = {
if cell.checkMark.isSelected == false {
let data:[String:String] = [self.Facilities[indexPath.row]: "Disinfected"]
self.InfoArray.append(data)
}
else {
self.InfoArray.remove(at: indexPath.row)
}
}
return cell
}
用户选择完选项后,它将点击 sendReport
按钮。然后,在该按钮内,您可以像这样 post 将数据保存到 firestore 文档。
db.collection("CollectionName").document("DocumentName").setData(["Facilities" : self.InfoArray])
您的 tableViewCell
文件应如下所示。
class YourTableViewCell: UITableViewCell {
@IBOutlet weak var checkMark: UIButton!
var tapButton: (() -> Void)? = nil
@IBAction func SetCheckMark(_ sender: UIButton) {
if checkMark.isSelected == true {
checkMark.setImage(UIImage(named: "Checkbox"), for: .normal)
checkMark.isSelected = false
}
else {
checkMark.setImage(UIImage(named: "UnCheckbox"), for: .normal)
checkMark.isSelected = true
}
tapButton?()
}
}
应该可以。如果您有任何问题,请立即告诉我。
New Error Message
Error Message.
现在,我明白了 error message。
已更新代码,此图中显示错误消息 link error message:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = runReportTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = valuesArray[indexPath.row]
cell.SetCheckMark(cell.checkMark) //Call 'SetCheckMark' function here
cell.tapButton = {
if cell.checkMark.isSelected == false {
let data:[String:String] = [self.Facilities[indexPath.row]: "Disinfected"]
self.InfoArray.append(data)
}
else {
self.InfoArray.remove(at: indexPath.row)
}
}
print("Responsibilities in cells: \(valuesArray)")
print("\(data)")
return cell
}
我让这段代码一直运行到“print("You taped cell #(indexPath.row)")”。此代码生成包含某些字段的此 firebase 文档:this document should have fields of the room/area text and values of "Disinfected" or "Not Disinfected" depending on whether the user selected that cell or left it unselected
因此,我现在需要此代码做的就是使用用户 select 编辑的单元格的文本 (valuesArray[indexPath.row]) 更新我的 Cloud Firestore 文档。在我的 viewController 上使用静态数量的按钮和标签之前,我已经完美地工作了,并且在我的 firebase Firestore 文档中得到了我想要的结果,如下所示:screenshot of when I had static information that I was updating in my firebase database after the user made all selections and tapped the "send report" button
但是,现在,我想知道如何在 firebase 文档中使用 selected 值“已消毒”或“未消毒”显示常量“房间 1”-“房间 21”键如果单元格是 selected/highlighted 或如果用户没有 select 单元格,我可以让我的代码自动写入该 firebase 文档“已消毒”,然后显示哪个单元格具有该值disinfected/notdisinfected 使用我从下方“Firestore 文档数据屏幕截图”中的数据中获取的单元格标签文本。
我认为这是因为我不是 100% 确定如何检查我创建的动态单元格是否 selected 或没有然后将“已消毒”或“未消毒”分配给 select在我的 Cloud Firestore 文档中编辑了单元格的文本。
如前所述,此代码打印正确的点击单元格编号和正确的点击单元格标签文本。它还成功创建了一个新的 Cloud Firestore 文档,其中没有 selected 按钮的值(“Disinfected”或“Not Disinfected”)及其匹配的单元格标签文本。
这是模拟器的屏幕截图Simulator Screenshot and a screenshot of the Cloud Firestore document data that I'm using for my cells' label text Firestore Document Data Screenshot。
import UIKit
import Firebase
import FirebaseFirestore
import SCLAlertView
class RunReportViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var runReportTableView: UITableView!
var namesDocumentRef:DocumentReference!
var userName = ""
var userEmail = ""
var data:[String] = []
var valuesArray:[String] = []
var selectedResponsibility:[String] = []
// var keysArray:[String] = []
override func viewDidLoad() {
super.viewDidLoad()
startObservingDB()
runReportTableView.delegate = self
runReportTableView.dataSource = self
// Do any additional setup after loading the view.
}
// Gets user's specific room(s)/area(s)/classroom(s) responsibilities from Cloud Firestore Database to be used for checking "Disinfected" or "Not Disinfected" in order to put the text as a cell label
func startObservingDB() {
var responsibilitiesDocumentRef:DocumentReference!
let db = Firestore.firestore()
let userID = Auth.auth().currentUser!.uid
responsibilitiesDocumentRef = db.collection("UserResponsibilities").document("McGrath").collection("Custodians").document("\(userID)")
responsibilitiesDocumentRef.addSnapshotListener { DocumentSnapshot, error in
if error != nil{
return
}
else {
guard let snapshot = DocumentSnapshot, snapshot.exists else {return}
guard let data = snapshot.data() else { return }
self.valuesArray = Array(data.values) as! Array<String>
// self.keysArray = Array(data.keys)
self.runReportTableView.reloadData()
print("Current data: \(data)")
print("Current data has the responsibilities: \(self.valuesArray)")
print("Current data totals \(self.valuesArray.count) items.")
}
}
}
@IBAction func sendReportTapped(_ sender: Any) {
getSelectionValues()
}
func getSelectionValues() {
let db = Firestore.firestore()
let userID = Auth.auth().currentUser!.uid
db.collection("Users").document("\(userID)").collection("UserInfo").getDocuments { (snapshot, err) in
if let err = err {
print("Error getting documents: \(err)")
} else {
for document in snapshot!.documents {
let docID = document.documentID
self.userName = document.get("Name") as! String
self.userEmail = document.get("Email") as! String
print("Current document is: \(docID)")
print("Current user's name: \(self.userName)")
}
db.collection("Run Reports").document("Custodians").collection("Custodians").document("\(String(describing: userID))").collection("Run Reports").document("\(self.getCurrentShortDate())").setData ([
"Name": "\(String(describing: self.userName))",
"Email": "\(String(describing: self.userEmail))",
"Admin": Bool(false),
"Last Updated": FieldValue.serverTimestamp(),
])
}
// getting values of selection code:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("The cell you tapped has the text: \(self.valuesArray[indexPath.row])")
// let selectedResponsibility = "\(self.valuesArray[indexPath.row])"
print("You tapped cell #\(indexPath.row)")
这就是问题所在。这段代码只是我在试验,尽管我更新 firebase 文档的代码有效——“设置责任 1 的状态”有效。它只是不适用于我上面关于动态单元格的信息,这些信息都是实验性的并且是错误的,因为不起作用:
// let currentUsersCellCount = self.valuesArray.count
let cell = self.runReportTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let dynamicCell = self.runReportTableView.cellForRow(at: indexPath)
if dynamicCell?.isSelected == true {
let status = "Disinfected"
let DocumentRef = db.collection("Run Reports").document("Custodians").collection("Custodians").document("\(String(describing: userID))").collection("Run Reports").document("\(self.getCurrentShortDate())")
// Set the status of Responsibility 1
DocumentRef.updateData(["\(self.valuesArray[indexPath.row])" : "\(status)"])
}
else if dynamicCell?.isSelected == false {
let status = "Not Disinfected"
let DocumentRef = db.collection("Run Reports").document("Custodians").collection("Custodians").document("\(String(describing: userID))").collection("Run Reports").document("\(self.getCurrentShortDate())")
// Set the status of Responsibility 1
DocumentRef.updateData(["\(self.valuesArray[indexPath.row])" : "\(status)"])
}
一切正常:
// Setup action for when "Send Report" and alert buttons are tapped
let appearance = SCLAlertView.SCLAppearance(
// Hide default button???
showCloseButton: false
)
// Create alert with appearance
let alert = SCLAlertView(appearance: appearance)
alert.addButton("Done", action: {
// Show SendReportViewController after successfully sent report and alert button is tapped
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "SendReportViewController")
vc.modalPresentationStyle = .overFullScreen
self.present(vc, animated: true)
// create button on alert
print("'Done' button was tapped.")
})
alert.showSuccess("Report Sent!", subTitle: "Your Run Report has been sent to your supervisor.", closeButtonTitle: "Done", timeout: nil, colorStyle: SCLAlertViewStyle.success.defaultColorInt, colorTextButton: 0xFFFFFF, circleIconImage: nil, animationStyle: .topToBottom)
}
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("The cell you tapped has the text: \(valuesArray[indexPath.row])")
// let selectedResponsibility = "\(valuesArray[indexPath.row])"
print("You tapped cell #\(indexPath.row)")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return valuesArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = runReportTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = valuesArray[indexPath.row]
print("Responsibilities in cells: \(valuesArray)")
print("\(data)")
return cell
}
// using date to create new firestore document with date as the title
func getCurrentShortDate() -> String {
let todaysDate = NSDate()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "(MM-dd-yy)"
let DateInFormat = dateFormatter.string(from: todaysDate as Date)
return DateInFormat
}
}
如果您想将有关您在 fireStore 文档中选择的单元格的信息存储为 Text of the cell
:Disinfected
或 Not Disinfected
,即 ConferenceRoom
:Disinfected
,那么这就是我的建议。
首先,在tableViewCell
文件中,添加以下属性
var tapButton: (() -> Void)? = nil //This will allow you to get the text of the row you have selected
然后,我想你的单元格内有一个按钮,在你的情况下它位于左侧,可以点击或取消点击。让我们将该按钮名称称为 checkMark
,这样它就会像这样在您的 tableviewCell
文件中声明。
@IBOutlet weak var checkMark: UIButton!
现在,添加一个函数 SetCheckMark
以便用户可以查看单元格是否已选中。此外,您将需要两个图像,它们将被分配给处于选中或未选中状态的按钮。
@IBAction func SetCheckMark(_ sender: UIButton) {
//If button is selected, then
if checkMark.isSelected == true {
checkMark.setImage(UIImage(named: "Check"), for: .normal)
checkMark.isSelected = false
}
else {
checkMark.setImage(UIImage(named: "UnCheck"), for: .normal)
checkMark.isSelected = true
}
tapButton?() //This is the property that we declared above.
}
现在,你差不多完成了。进入你的主文件。首先在File开头添加一个字典来保存信息。
var InfoArray:[[String:String]] = [["":""]]
现在,在您的 tableView cellForRowAt indexPath: IndexPath
函数中,添加这些行。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = runReportTableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.label.text = valuesArray[indexPath.row]
cell.SetCheckMark(cell.checkMark) //Call `SetCheckmark` function here
cell.tapButton = {
if cell.checkMark.isSelected == false {
let data:[String:String] = [self.Facilities[indexPath.row]: "Disinfected"]
self.InfoArray.append(data)
}
else {
self.InfoArray.remove(at: indexPath.row)
}
}
return cell
}
用户选择完选项后,它将点击 sendReport
按钮。然后,在该按钮内,您可以像这样 post 将数据保存到 firestore 文档。
db.collection("CollectionName").document("DocumentName").setData(["Facilities" : self.InfoArray])
您的 tableViewCell
文件应如下所示。
class YourTableViewCell: UITableViewCell {
@IBOutlet weak var checkMark: UIButton!
var tapButton: (() -> Void)? = nil
@IBAction func SetCheckMark(_ sender: UIButton) {
if checkMark.isSelected == true {
checkMark.setImage(UIImage(named: "Checkbox"), for: .normal)
checkMark.isSelected = false
}
else {
checkMark.setImage(UIImage(named: "UnCheckbox"), for: .normal)
checkMark.isSelected = true
}
tapButton?()
}
}
应该可以。如果您有任何问题,请立即告诉我。