ios 如何使用swift而不是实现新的控制器来合计tableview第三部分中各个年龄组的出勤率?

wi3ka0sx  于 2023-02-01  发布在  iOS
关注(0)|答案(1)|浏览(114)

以下是迄今为止已实施的内容的图片。

**目的:**以表格视图显示第三部分中年龄组的出勤总数。
我们应用的内容:已尝试应用带有新变量的标签,该变量可以计算增加和减少按钮功能的单元格。
**问题是什么:**在表视图的第三部分中,我们只希望标签显示年龄组的总出勤率,但仍会重复点击增加和减少按钮
我们的尝试:1.尝试使用新变量应用标签,该变量可以计算增加和减少按钮功能的单元格,不幸的是,如果[“0”]用于新变量以实现总和,则应用程序崩溃。--〉var itemValue 2 = [“0”] 2.尝试使用新控制器实现,但发生了同样的事情。

下面是类AdditionalGuestInformationVC:的代码:

import UIKit
import ObjectiveC
import SSSpinnerButton

class AdditionalGuestInforTVCell: UITableViewCell {
        
    @IBOutlet weak var lblName: UILabel!
    @IBOutlet weak var lblDetails: UILabel!
    
    @IBOutlet var btnMinus: UIButton!
    @IBOutlet var lblValue: UILabel!
    @IBOutlet var btnPlus: UIButton!
}

class AdditionalGuestInformationVC: UIViewController, UITableViewDelegate, UITableViewDataSource {

    let section = ["Male", "Female", "total"]

    let itemsName = [["Shishu", "Baal", "Kishore", "Tarun", "Yuva", "Jyeshta"], ["Shishu", "Baalika", "Kishori", "Taruni", "Yuvati", "Jyeshtaa"], ["Total:"]]
    let itemsDetails = [["Below 5 Years - Pre-primary ", "5 to 11 Years - Primary School", "11 to 16 Years - Middle School", "17 to 25 Years - High School/College", "25 to 60 Years - Adults", ">60 Years - Senior citizen"], ["Below 5 Years - Pre-primary ", "5 to 11 Years - Primary School", "11 to 16 Years - Middle School", "17 to 25 Years - High School/College", "25 to 60 Years - Adults", ">60 Years - Senior citizen"],["Attendees"]]
    var itemValue = [["0", "0", "0", "0", "0", "0"], ["0", "0", "0", "0", "0", "0"], ["0"]]
   
    
    var dicMember = [[String:Any]]()
    
    var strDate = ""
    var utsavName = ""
    
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet var lblShakhaName: UILabel!
    @IBOutlet var lblDate: UILabel!
    
    @IBOutlet var btnSubmit: SSSpinnerButton!

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
        self.fillData()

    }
    
    override func viewWillAppear(_ animated: Bool) {
        navigationBarDesign(txt_title: "guest_information".localized, showbtn: "back")
        self.firebaseAnalytics(_eventName: "AdditionalGuestInfoVC")
    }
    
    
    func fillData() {
        self.lblDate.text = strDate
    }
    
    @objc func onMinusClick(_ sender: UIButton) {
        
        let sectionIndex = ((sender.tag / 10) - 10)
        let rowIndex = (sender.tag % 10)

        let indexPath = NSIndexPath(row: rowIndex, section: sectionIndex)
        let cell = tableView.cellForRow(at: indexPath as IndexPath) as? AdditionalGuestInforTVCell
        
        var strVal : Int = Int((cell?.lblValue.text)!)!

        if strVal > 0 {
            strVal -= 1
        }
        self.itemValue[sectionIndex][rowIndex] = "\(Int(strVal))"
        tableView.reloadRows(at:[indexPath as IndexPath], with:.automatic)

    }
    
    @objc func onPlusClick(_ sender: UIButton) {
        let sectionIndex = ((sender.tag / 10) - 10)
        let rowIndex = (sender.tag % 10)

        let indexPath = NSIndexPath(row: rowIndex, section: sectionIndex)
        let cell = tableView.cellForRow(at: indexPath as IndexPath) as? AdditionalGuestInforTVCell
        
        var strVal : Int = Int((cell?.lblValue.text)!)!

        if strVal < 99 {
            strVal += 1
        }
        self.itemValue[sectionIndex][rowIndex] = "\(Int(strVal))"
        tableView.reloadRows(at:[indexPath as IndexPath], with:.automatic)
    }
    
    @IBAction func onPreviewClick(_ sender: UIButton) {
        let storyBoard = UIStoryboard(name: "Main", bundle: nil)
        let vc = storyBoard.instantiateViewController(withIdentifier: "AttendancePreviewVC") as! AttendancePreviewVC
        vc.itemsName = self.itemsName
        vc.itemsDetails = self.itemsDetails
        vc.itemValue = self.itemValue
        vc.dicMember = self.dicMember
        self.navigationController?.pushViewController(vc, animated: true)
    }
    
    @IBAction func onSubmitClick(_ sender: UIButton) {
        btnSubmit.startAnimate(spinnerType: SpinnerType.circleStrokeSpin, spinnercolor: .white, spinnerSize: 20, complete: {
            // Your code here
            self.addSankhyaAPI()
            let disableMyButton = sender as? UIButton
            disableMyButton?.isEnabled = false
        })
    }
    
    // MARK: TableView Methods
    
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?
    {
        return self.section[section]
    }
    
    func numberOfSections(in tableView: UITableView) -> Int
    {
    // #warning Incomplete implementation, return the number of sections
        return self.section.count
    }
    
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let rect = CGRect(x: 20, y: 0, width: tableView.frame.size.width - 40, height: 60)
        let footerView = UIView(frame:rect)
        footerView.backgroundColor = UIColor.init(red: 229.0/255.0, green: 229.0/255.0, blue: 229.0/255.0, alpha: 1.0)
        
        let lblTitle = UILabel(frame: CGRect(x: 20.0, y: footerView.center.y / 2, width: 160, height: 30))
        lblTitle.text = "Guest Information"
        lblTitle.font = UIFont(name: "SourceSansPro-Regular", size: 20.0)
        lblTitle.backgroundColor = UIColor.clear
        lblTitle.textColor = UIColor.init(red: 154.0/255.0, green: 154.0/255.0, blue: 154.0/255.0, alpha: 1.0)
        
        let lblGender = UILabel(frame: CGRect(x: 30.0 + lblTitle.frame.width, y: footerView.center.y / 2, width: 80, height: 30))
        lblGender.text = self.section[section]
        lblGender.font = UIFont(name: "SourceSansPro-SemiBold", size: 16.0)
        lblGender.textColor = UIColor.black
        lblGender.backgroundColor = UIColor.init(red: 255.0/255.0, green: 230.0/255.0, blue: 190.0/255.0, alpha: 1.0)
        lblGender.layer.cornerRadius = 15.0
        lblGender.layer.masksToBounds = true
        lblGender.textAlignment = .center
        
        footerView.addSubview(lblGender)
        footerView.addSubview(lblTitle)
        return footerView
    }

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 60  // or whatever
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.itemsName[section].count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "AdditionalGuestInforTVCell", for: indexPath) as! AdditionalGuestInforTVCell

        cell.lblName.text = self.itemsName[indexPath.section][indexPath.row]
        cell.lblDetails.text = self.itemsDetails[indexPath.section][indexPath.row]

        cell.lblValue.text = self.itemValue[indexPath.section][indexPath.row]
        cell.btnMinus.addTarget(self, action: #selector(onMinusClick(_:)), for: .touchUpInside)
        cell.btnPlus.addTarget(self, action: #selector(onPlusClick(_:)), for: .touchUpInside)
        
        let strSection : String = "\(indexPath.section + 10)"
        let strRow = "\(indexPath.row)"
        
        cell.btnPlus.tag = Int(strSection + strRow)!
        cell.btnMinus.tag = Int(strSection + strRow)!
        cell.lblValue.tag = Int(strSection + strRow)!
  

        return cell
    }

    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension //Choose your custom row height
    }

    
    func addSankhyaAPI() {
        
        let arrFilter : [String] = self.dicMember.filter { $0["isPresent"] as! String == "true" }.map { $0["member_id"]! as! String }
        let stringArr = arrFilter.joined(separator: " ")
        let stringArray = stringArr.replacingOccurrences(of: " ", with: ", ", options: .literal, range: nil)

        
        var parameters: [String: Any] = [:]
        parameters["user_id"] = _appDelegator.dicMemberProfile![0]["user_id"] as? String // dicUserDetails["user_id"]
        parameters["event_date"] = strDate
        parameters["org_chapter_id"] = _appDelegator.dicMemberProfile![0]["shakha_id"]
        parameters["utsav"] = utsavName
        parameters["member_id"] = stringArray
        parameters["shishu_male"] = self.itemValue[0][0]
        parameters["baal"] = self.itemValue[0][1]
        parameters["kishore"] = self.itemValue[0][2]
        parameters["tarun"] = self.itemValue[0][3]
        parameters["yuva"] = self.itemValue[0][4]
        parameters["proudh"] = self.itemValue[0][5]
        parameters["shishu_female"] = self.itemValue[1][0]
        parameters["baalika"] = self.itemValue[1][1]
        parameters["kishori"] = self.itemValue[1][2]
        parameters["taruni"] = self.itemValue[1][3]
        parameters["yuvati"] = self.itemValue[1][4]
        parameters["proudha"] = self.itemValue[1][5]
        parameters["total:"] = self.itemValue[2]
        parameters["api"] = "yes"
        
        print(parameters)
        
        APIManager.sharedInstance.callPostApi(url: APIUrl.add_sankhya, parameters: parameters) { (jsonData, error) in
            if error == nil
            {
                if let status = jsonData!["status"].int
                {
                    if status == 1
                    {
                        self.btnSubmit.stopAnimationWithCompletionTypeAndBackToDefaults(completionType: .success, backToDefaults: true, complete: {
                            // Your code here
                            if let strMessage = jsonData!["message"].string {
                                showAlert(title: APP.title, message: strMessage)
                            }
                        })
                    }else {
                        self.btnSubmit.stopAnimationWithCompletionTypeAndBackToDefaults(completionType: .fail, backToDefaults: true, complete: {
                            // Your code here
                            if let strError = jsonData!["message"].string {
                                showAlert(title: APP.title, message: strError)
                            }
                        })
                    }
                } else {
                    self.btnSubmit.stopAnimationWithCompletionTypeAndBackToDefaults(completionType: .fail, backToDefaults: true, complete: {
                        // Your code here
                        if let strError = jsonData!["message"].string {
                            showAlert(title: APP.title, message: strError)
                        }
                    })
                }
            }
        }
    }
}
w8f9ii69

w8f9ii691#

您希望将按钮操作移动到AdditionalGuestInforTVCell cell类内部,然后使用closure通知控制器值发生了更改。
使用第二个UITableViewCell类作为"Total"单元格-带有两个标签,因此它看起来如下所示:

当你的AdditionalGuestInforTVCell单元告诉控制器它的值改变了,更新你的数据,得到所有"项"的总和,并重新加载第三部分。
这里有一个简单的例子...
首先,让我们使用struct来定义数据:

struct ItemStruct {
    var itemName: String = ""
    var itemDetails: String = ""
    var itemCount: Int = 0
}

在控制器中,我们将使用如下的var属性:

// our data is now an Array of ItemStruct Arrays
//  so we'll have one Array per section
var myData: [[ItemStruct]] = []

我们将这样初始化数据。
viewDidLoad()中:

override func viewDidLoad() {
    super.viewDidLoad()
    
    // all the normal view setup

    myData = getData()
}

func getData() -> [[ItemStruct]] {
    let itemsName = [
        ["Shishu", "Baal", "Kishore", "Tarun", "Yuva", "Jyeshta"],
        ["Shishu", "Baalika", "Kishori", "Taruni", "Yuvati", "Jyeshtaa"],
    ]
    let itemsDetails = [
        ["Below 5 Years - Pre-primary ", "5 to 11 Years - Primary School", "11 to 16 Years - Middle School", "17 to 25 Years - High School/College", "25 to 60 Years - Adults", ">60 Years - Senior citizen"],
        ["Below 5 Years - Pre-primary ", "5 to 11 Years - Primary School", "11 to 16 Years - Middle School", "17 to 25 Years - High School/College", "25 to 60 Years - Adults", ">60 Years - Senior citizen"],
    ]
    
    var tmpArray: [[ItemStruct]] = []
    
    // let's fill our data with names and details
    for (names, details) in zip(itemsName, itemsDetails) {
        var secData: [ItemStruct] = []
        for i in 0..<names.count {
            let d = ItemStruct(itemName: names[i], itemDetails: details[i], itemCount: 0)
            secData.append(d)
        }
        tmpArray.append(secData)
    }
    
    return tmpArray

}

下面是一个完整的、可运行的示例,我们通过代码创建所有内容--没有@IBOutlet@IBAction连接--因此您所需要做的就是将普通UIViewController的自定义类赋值为AdditionalGuestInformationVC,我尝试在代码中包含足够多的行内注解以使事情更清楚:

struct ItemStruct {
    var itemName: String = ""
    var itemDetails: String = ""
    var itemCount: Int = 0
}

class TotalCell: UITableViewCell {
    
    var lblTitle = UILabel()
    var lblValue = UILabel()
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() {
        
        // label properties
        lblTitle.text = "Total Attendees:"
        lblValue.textAlignment = .center
        
        // add views to contentView
        [lblTitle, lblValue].forEach { v in
            v.translatesAutoresizingMaskIntoConstraints = false
            contentView.addSubview(v)
        }
        
        // use content view's defaualt margins
        let g = contentView.layoutMarginsGuide
        
        // this avoids autolayout complaints
        let c = lblTitle.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0)
        c.priority = .required - 1
        
        NSLayoutConstraint.activate([
            
            // Name label Top / Leading
            lblTitle.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
            lblTitle.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            lblTitle.heightAnchor.constraint(equalToConstant: 50.0),
            c,
            
            // Value label Trailing
            lblValue.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
            
            lblValue.widthAnchor.constraint(equalToConstant: 40.0),
            
            // vertically center Value label
            lblValue.centerYAnchor.constraint(equalTo: g.centerYAnchor),
            
        ])
        
    }
    
    func fillData(_ value: Int) {
        lblValue.text = "\(value)"
    }
    
}

class AdditionalGuestInforTVCell: UITableViewCell {

    // closure to inform the controller that the count changed
    var countChanged: ((UITableViewCell, Int) -> ())?
    
    var lblName = UILabel()
    var lblDetails = UILabel()
    
    var btnMinus = UIButton()
    var lblValue = UILabel()
    var btnPlus = UIButton()
    
    // we'll automatically update the value label when the count changes
    var currentItemCount: Int = 0 {
        didSet {
            lblValue.text = "\(currentItemCount)"
        }
    }
    
    @objc func minusTap() {
        if currentItemCount > 0 {
            // decrement current count
            currentItemCount -= 1
            
            // inform the controller
            countChanged?(self, currentItemCount)
        }
    }
    
    @objc func plusTap() {
        // increment current count
        currentItemCount += 1
        
        // inform the controller
        countChanged?(self, currentItemCount)
    }
    
    // we'll fill the labels from our data struct object
    func fillData(_ data: ItemStruct) {
        lblName.text = "\(data.itemName)"
        lblDetails.text = "\(data.itemDetails)"
        self.currentItemCount = data.itemCount
    }
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() {
        
        // label properties
        lblDetails.font = .systemFont(ofSize: 14.0)
        lblDetails.textColor = .gray
        lblDetails.numberOfLines = 0
        
        lblValue.textAlignment = .center
        
        // button titles
        btnMinus.setTitle("-", for: [])
        btnPlus.setTitle("+", for: [])
        
        // button style
        [btnMinus, btnPlus].forEach { b in
            b.setTitleColor(.black, for: .normal)
            b.setTitleColor(.lightGray, for: .highlighted)
            b.layer.cornerRadius = 6
            b.layer.borderWidth = 1
            b.layer.borderColor = UIColor.lightGray.cgColor
        }
        
        // add views to contentView
        [lblName, lblDetails, btnMinus, lblValue, btnPlus].forEach { v in
            v.translatesAutoresizingMaskIntoConstraints = false
            contentView.addSubview(v)
        }
        
        // use content view's defaualt margins
        let g = contentView.layoutMarginsGuide
        
        // this avoids autolayout complaints
        let c = lblDetails.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0)
        c.priority = .required - 1
        
        NSLayoutConstraint.activate([
            
            // Name label Top / Leading
            lblName.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
            lblName.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            
            // Details label Top (to Name label Bottom) / Leading / Bottom
            lblDetails.topAnchor.constraint(equalTo: lblName.bottomAnchor, constant: 6.0),
            lblDetails.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            c,

            // plus button Trailing
            btnPlus.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
            
            // Value label Trailing (to Plus button Leading)
            lblValue.trailingAnchor.constraint(equalTo: btnPlus.leadingAnchor, constant: 0.0),
            
            // Minus button Trailing (to Value label Leading)
            btnMinus.trailingAnchor.constraint(equalTo: lblValue.leadingAnchor, constant: 0.0),
            
            // buttons and Value label centered vertically
            btnPlus.centerYAnchor.constraint(equalTo: g.centerYAnchor),
            lblValue.centerYAnchor.constraint(equalTo: g.centerYAnchor),
            btnMinus.centerYAnchor.constraint(equalTo: g.centerYAnchor),
            
            btnMinus.widthAnchor.constraint(equalToConstant: 40.0),
            btnPlus.widthAnchor.constraint(equalTo: btnMinus.widthAnchor),
            lblValue.widthAnchor.constraint(equalTo: btnMinus.widthAnchor),

            // Details label Trailing ("right edge")
            lblDetails.trailingAnchor.constraint(equalTo: btnMinus.leadingAnchor, constant: -8.0),
            
        ])

        btnMinus.addTarget(self, action: #selector(minusTap), for: .touchUpInside)
        btnPlus.addTarget(self, action: #selector(plusTap), for: .touchUpInside)

    }
    
}

class AdditionalGuestInformationVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    let section = ["Male", "Female", "Total"]
    
    var tableView: UITableView!
    
    var myData: [[ItemStruct]] = []

    func getData() -> [[ItemStruct]] {
        let itemsName = [
            ["Shishu", "Baal", "Kishore", "Tarun", "Yuva", "Jyeshta"],
            ["Shishu", "Baalika", "Kishori", "Taruni", "Yuvati", "Jyeshtaa"],
        ]
        let itemsDetails = [
            ["Below 5 Years - Pre-primary ", "5 to 11 Years - Primary School", "11 to 16 Years - Middle School", "17 to 25 Years - High School/College", "25 to 60 Years - Adults", ">60 Years - Senior citizen"],
            ["Below 5 Years - Pre-primary ", "5 to 11 Years - Primary School", "11 to 16 Years - Middle School", "17 to 25 Years - High School/College", "25 to 60 Years - Adults", ">60 Years - Senior citizen"],
        ]
        
        var tmpArray: [[ItemStruct]] = []
        
        // let's fill our data with names and details
        for (names, details) in zip(itemsName, itemsDetails) {
            var secData: [ItemStruct] = []
            for i in 0..<names.count {
                let d = ItemStruct(itemName: names[i], itemDetails: details[i], itemCount: 0)
                secData.append(d)
            }
            tmpArray.append(secData)
        }
        
        return tmpArray

    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .systemGreen
        
        tableView = UITableView(frame: .zero, style: .insetGrouped)
        
        tableView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(tableView)
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            
            // Top / Leading / Trailing inset by 20-points (so we can see the table frame)
            tableView.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
            tableView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            tableView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            
            // let's leave some space at the bottom
            tableView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -80.0),
            
        ])
        
        // register the "input" cells
        tableView.register(AdditionalGuestInforTVCell.self, forCellReuseIdentifier: "AdditionalGuestInforTVCell")
        // register the "Total" cell
        tableView.register(TotalCell.self, forCellReuseIdentifier: "totalCell")
        
        tableView.dataSource = self
        tableView.delegate = self

        myData = getData()
        
    }

    // MARK: TableView Methods
    
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return self.section[section]
    }
    
    func numberOfSections(in tableView: UITableView) -> Int {
        // add 1 for the Total section
        return myData.count + 1
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // if it's the last section, it's the Total section
        if section == myData.count {
            return 1
        }
        return myData[section].count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        // if it's the last section, it's the Total section
        if indexPath.section == myData.count {
            let cell = tableView.dequeueReusableCell(withIdentifier: "totalCell", for: indexPath) as! TotalCell
            
            // get the total of values from all data
            var total: Int = 0
            for i in 0..<self.myData.count {
                total += self.myData[i].reduce(0) { $0 + $1.itemCount }
            }
            
            cell.fillData(total)
            
            return cell
        }
        
        // it's not the last section
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "AdditionalGuestInforTVCell", for: indexPath) as! AdditionalGuestInforTVCell
        cell.fillData(myData[indexPath.section][indexPath.row])
        
        // add closure
        cell.countChanged = { [weak self] aCell, aValue in
            guard let self = self,
                  let thisCell = aCell as? AdditionalGuestInforTVCell,
                  let idxPath = self.tableView.indexPath(for: thisCell)
            else { return }
            
            // update the data
            self.myData[idxPath.section][idxPath.row].itemCount = aValue
            
            // reload the last section (the "Total" section)
            self.tableView.reloadSections([self.myData.count], with: .none)
            
        }
        return cell

    }
    
}

在运行时应如下所示:
第一节第一节第一节第二节第一节

相关问题