Reputation: 43
Now, I'm getting this error message.
Updated Code with error message shown in this image 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
}
I have this code working all the way up to "print("You tapped cell #(indexPath.row)")." This code produces this firebase document with some fields: 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
So, all I need this code to do now is update my Cloud Firestore document with the text (valuesArray[indexPath.row]) of the cells that were selected by the users. I had this working perfectly before using a static number of buttons and labels on my viewController and had my desired result in my firebase Firestore document like this: 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
However, now, instead of displaying a constant "Room 1"-"Room 21" keys in the firebase document with the selected value of "Disinfected" or "Not Disinfected" I am wondering how I can have my code automatically write to that firebase document "Disinfected" if the cell is selected/highlighted or "Not Disinfected" if the user does not select the cell and, then display which cell had that value of disinfected/notdisinfected using the cell's label text which I am getting from the data in the "Firestore Document Data Screenshot" down below.
I think its because I'm not 100% sure how to check if the dynamic cells I created are selected or not and then assign either "Disinfected" or "Not Disinfected" to that selected cell's text in my Cloud Firestore document.
As aforementioned, this code prints the correct number of the tapped cell and the correct label text of the tapped cell. It also successfully creates a new Cloud Firestore document without the values ("Disinfected" or "Not Disinfected") of the selected buttons and their matching cell label text.
Here's a screenshot of the simulator 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)")
This is where the issue is at. This code is just me experimenting, although the code where I update the firebase document works--"Set the status of Responsibility 1" works. Its just not working for the information I have above it about the dynamic cell which is all experimental and wrong since doesnt work:
// 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)"])
}
This all works perfectly fine:
// 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
}
}
Upvotes: 0
Views: 462
Reputation: 553
If you want to store the information about the cell you have selected in fireStore document as Text of the cell
: Disinfected
or Not Disinfected
, i.e ConferenceRoom
: Disinfected
, then this is what I would suggest.
Firstly, inside the tableViewCell
file, add following properties
var tapButton: (() -> Void)? = nil //This will allow you to get the text of the row you have selected
Then, I suppose you have a button inside your cell which in your case is on left side and it can be tapped or untapped. Let call that button name as checkMark
so it will be declared inside your tableviewCell
file like so.
@IBOutlet weak var checkMark: UIButton!
Now, add a function SetCheckMark
so user can see wether a cell is checked or unchecked. Also, you would need two images which would be assigned to button in checked or unchecked state.
@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.
}
Now, you are almost done. Come inside your Main file. Firstly, add a dictionary at the start of File to save information.
var InfoArray:[[String:String]] = [["":""]]
Now, inside your tableView cellForRowAt indexPath: IndexPath
function, add these lines.
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
}
After the user is done selecting the options, it will tap the sendReport
button. Then, inside that button you can post the data to firestore document like this.
db.collection("CollectionName").document("DocumentName").setData(["Facilities" : self.InfoArray])
Your tableViewCell
file should look something like this.
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?()
}
}
It should work. If you get any problem, do let me know instantly.
Upvotes: 1