【问题标题】:Dealing with dynamic cells in a UITableView?处理 UITableView 中的动态单元格?
【发布时间】:2020-07-07 07:41:30
【问题描述】:

New Error Message

Error Message.

现在,我收到了error message

已更新代码,错误消息显示在此图片链接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
}

我让这段代码一直工作到“打印(“你点击了单元格#(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

所以,我现在需要此代码做的就是使用用户选择的单元格的文本 (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 文档“已消毒”;如果用户未选择单元格,则为“未消毒”,然后使用我从中获取的单元格的标签文本显示哪个单元格具有已消毒/未消毒的值下方“Firestore 文档数据截图”中的数据。

我认为这是因为我不是 100% 确定如何检查我创建的动态单元格是否被选中,然后在我的 Cloud Firestore 文档中为该选定单元格的文本分配“已消毒”或“未消毒”。

如前所述,此代码打印点击单元格的正确编号和点击单元格的正确标签文本。它还成功创建了一个新的 Cloud Firestore 文档,其中没有所选按钮的值(“已消毒”或“未消毒”)及其匹配的单元格标签文本。

这是模拟器 Simulator Screenshot 的屏幕截图和我用于单元格标签文本 Firestore Document Data Screenshot 的 Cloud Firestore 文档数据的屏幕截图。

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
}

}

【问题讨论】:

  • 我不明白你的问题是什么?你能否通过编辑并提供一些关于你想在这里做什么的明确细节来进一步澄清它?
  • @Coder,我更新了一点,如果您需要更多说明,请告诉我。我已经准备好解决这个问题并完成这项工作,伙计
  • @Coder,基本上,我的应用程序中有这个 tableview,它已经动态地将我的 firestore 数据库中的文档中的文本显示到它的单元格上。为了实现这一点,我在代码中引用了文档,然后将文档数据作为一个数组获取(我想解决的另一个问题是让数组按它们的键排序 [例如,一个键:“区域 1”]或者当我将它放入我的代码时的时间戳,以便它在我的表格视图中按顺序显示)并使用该数组在我的表格视图的单元格中显示文档的字段/值,以获取该文档中的字段/值的动态数量。 [1/2]
  • @Coder,现在,我需要做的是,假设用户选择了在 tableview 中动态显示的所有单元格/行,然后我需要更新我之前创建的 firebase 文档代码(开始时只有文档字段:“Admin”、“Email”、“Last Updated”和“Name”)具有与特定用户的单元格相同数量的字段(记住单元格是动态的显示),字段文本是单元格文本,以及单元格的状态(选择还是未选择)。 [2/2]
  • 示例:如果您查看我在主帖正文中链接的“模拟器屏幕截图”,假设用户只选择了前两个单元格(表明他对前两个房间/区域进行了消毒并且没有对剩余的房间/区域进行消毒[不要介意我那里的文字说明;已过时,只是还没有更改]),然后点击屏幕底部的“发送报告”按钮。我的应用程序应该使用以下字段更新文档(如我在本文正文中链接的第一张图片所示):“会议室”,其值应为“已消毒”。你明白了,其余的都是“NotDis”

标签: swift xcode dynamic tableview


【解决方案1】:

如果你想将你在fireStore文档中选择的单元格的信息存储为Text of the cellDisinfectedNot Disinfected,即ConferenceRoomDisinfected,那么这就是我的建议。

首先,在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 按钮。然后,在该按钮内,您可以像这样将数据发布到 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?()
    }
 }

它应该工作。如果您有任何问题,请立即告诉我。

【讨论】:

猜你喜欢
  • 2012-10-03
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 2019-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多