SWIFT & Storyboard - 带有部分的表视图,每个部分都包含一个复选框列表

SWIFT & Storyboard - Tableview with Sections and each them contains a list of checkboxes

提问人:Cristian Capannini 提问时间:7/7/2023 最后编辑:Cristian Capannini 更新时间:7/8/2023 访问量:73

问:

Goodmornig,我需要一些帮助来显示带有部分的表视图和每个部分的自定义 tableviewcell。我希望实现这个目标,如下图所示:Goal

从图片中我们了解到,如果选中了带有复选框及其 ID 的兴趣列表>类别。

我已经构建了 tableview 单元格,如下所示:

TableViewCell

这是tableview的代码

    class InteresseCell2: UITableViewCell {

    
    @IBOutlet weak var checkBoxInteresse: CheckBoxButton!
    
    @IBOutlet weak var labelInteresse: UILabel!
    
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }
    
    //MARK:- setDescrizioneInteresse
    func setDescrizioneInteresse(_ descrizione: String)
    {
        self.labelInteresse.text = descrizione
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }
    
}

其中 CheckBoxButton 是我的自定义类:

class CheckBoxButton: UIButton {

    // Images
    let checkedImage = UIImage(named: "box_checked")! as UIImage
    let uncheckedImage = UIImage(named: "box_unchecked")! as UIImage
    
    // Bool property
    var isChecked: Bool = false {
        didSet{
            if isChecked == true {
                self.setImage(uncheckedImage, for: .normal)
            } else {
                self.setImage(checkedImage, for: .normal)
            }
        }
    }
    
    override func awakeFromNib() {
        self.isUserInteractionEnabled = true
        self.addTarget(self, action: #selector(CheckBoxButton.buttonClicked), for: .touchUpInside)
                self.isChecked = false
    }
    
    @objc func buttonClicked(sender: UIButton) {
        if sender == self {
            if isChecked == true {
                isChecked = false
            } else {
                isChecked = true
            }
        }
    }

}

我的json是这样形成的:

{
  "success": 1,
  "interessi": [
    {
      "cid": "1",
      "categoria": "Marketing & Comunicazione",
      "elenco": [
        {
          "id": "5",
          "cid": "1",
          "descrizione": "Advertising"
        },
        {
          "id": "4",
          "cid": "1",
          "descrizione": "Branding"
        },
        {
          "id": "2",
          "cid": "1",
          "descrizione": "Content creation"
        },
        {
          "id": "6",
          "cid": "1",
          "descrizione": "Copywriting"
        },
        {
          "id": "3",
          "cid": "1",
          "descrizione": "Influencer Marketing"
        },
        {
          "id": "12",
          "cid": "1",
          "descrizione": "Media"
        },
        {
          "id": "7",
          "cid": "1",
          "descrizione": "Personal Branding"
        },
        {
          "id": "1",
          "cid": "1",
          "descrizione": "Social Media"
        },
        {
          "id": "10",
          "cid": "1",
          "descrizione": "Strategy"
        },
        {
          "id": "8",
          "cid": "1",
          "descrizione": "Sviluppo Prodotto"
        },
        {
          "id": "9",
          "cid": "1",
          "descrizione": "Trade Marketing"
        },
        {
          "id": "11",
          "cid": "1",
          "descrizione": "UX/Web & Graphic Design"
        }
      ]
    },
    {
      "cid": "2",
      "categoria": "Sviluppo della persona",
      "elenco": [
        {
          "id": "13",
          "cid": "2",
          "descrizione": "Coaching"
        },
        {
          "id": "16",
          "cid": "2",
          "descrizione": "Counseling"
        },
        {
          "id": "15",
          "cid": "2",
          "descrizione": "Crescita Personale"
        },
        {
          "id": "14",
          "cid": "2",
          "descrizione": "Mentoring"
        },
        {
          "id": "17",
          "cid": "2",
          "descrizione": "Orientamento Post-Universitario"
        }
      ]
    }
  ]
}

我的InteresseSection对象类是:

class InteresseSection: NSObject {
    
    var categoria: String = String()
   
    var interessi: [Interesse] = []
    
}

Interesse 类是:

class Interesse: NSObject {
    
    var id: String = String()
    var cid: String = String()
    var descrizione: String = String()
    
}

获取json数据的代码如下

func getData() {
        print("InteressiRegistrazioneVC getData")
        
        DispatchQueue.main.async {
            self.refreshControl.endRefreshing()
        }
        
        
        let getListaInteressiString = "\(Constants.GET_LISTA_INTERESSI_URL)"
        let interessiURL: URL = URL(string: getListaInteressiString)!
         
        var request = URLRequest(url: interessiURL)
        request.httpMethod = "POST"
        
        let headers = ["Content-Type": "application/x-www-form-urlencoded"]
        request.allHTTPHeaderFields = headers
        
        let parameters: [String: Any] = [
            "user_id": UserDefaults.standard.string(forKey: "user_id") ?? "-1",
            "email": UserDefaults.standard.string(forKey: "email") ?? "[email protected]",
            "r": "" // mettere il campo search ma è
        ]
        
        request.httpBody = parameters.percentEncoded()
        
        let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
            guard let data = data else {
                print("InteressiRegistrazioneVC getData error: \(String(describing: error))")
                DispatchQueue.main.async {
                    //self.hideLoading()
                    //self.isLoading = false
                }
                return
            }
            
            if let httpResponse = response as? HTTPURLResponse {
                print("InteressiRegistrazioneVC getData status code: \(httpResponse.statusCode)")
                if httpResponse.statusCode == 200 {
                    
                } else {
                    
                }
            }
            
            // converting data to string
            
            if let dataAsString = String.init(data: data, encoding: String.Encoding.utf8) {
                print("InteressiRegistrazioneVC getData dataAsString: \(dataAsString)")
            }
            
            
            do {
                if let jsonDictionary = try JSONSerialization.jsonObject(with: data, options : .allowFragments) as? Dictionary<String, Any> {
                    
                    let interessiArray = jsonDictionary["interessi"] as? NSArray ?? []
                    
                    self.allInteressi.removeAll()
                    
                    if interessiArray.count == 0 {
                        
                        DispatchQueue.main.async {
                            //self.noDataView.isHidden = false
                            //self.tableView.isHidden = true
                            
                        }
                        
                    } else {
                        
                        DispatchQueue.main.async {
                            //self.tableView.isHidden = false
                            //self.noDataView.isHidden = true
                           
                        }
                         
                        for sezione in interessiArray {
                            if let dictionarySection = sezione as? [String: Any] {
                                let elenco = dictionarySection["elenco"] as? NSArray ?? []
                                
                                var interessiInSection: [Interesse] = []
                                
                                for itemElenco in elenco {
                                    
                                    if let interesse = itemElenco as? [String: Any] {
                                     
                                        let id = interesse["id"] as? String ?? ""
                                        let cid = interesse["cid"] as? String ?? ""
                                        let descrizione = interesse["descrizione"] as? String ?? ""
                                        
                                        Logger.show(msg: "\n")
                                        Logger.show(msg: "InteressiRegistrazioneVC item id: \(String(describing: id))")
                                        Logger.show(msg: "InteressiRegistrazioneVC item cid: \(String(describing: cid))")
                                        Logger.show(msg: "InteressiRegistrazioneVC item descrizione: \(String(describing: descrizione))")
                                        
                                        let newInteresse = Interesse()
                                        newInteresse.id = id
                                        newInteresse.cid = cid
                                        newInteresse.descrizione = descrizione
                                        
                                       interessiInSection.append(newInteresse) // raccolgo tutti i prodotti presenti nella i-esima sezione
                                        
                                    } // interesse itemelenco
                                    
                                    
                                } //elenco
                                
                                
                                let newSection = InteresseSection()
                                
                                let categoria = dictionarySection["categoria"] as? String ?? ""
                                Logger.show(msg: "InteressiRegistrazioneVC getData categoria: \(categoria)")
                                
                                newSection.categoria = categoria
                                newSection.interessi = interessiInSection
                                
                                //self.allInteressi.append(newSection)
                                
                                
                               
                            } // dictionary section
                            
                        } // sezione
                        
                    }
                    
                    // aggiorno la tabella dopo aver scaricato i dati
                    DispatchQueue.main.async {
                      
                    }
                    
                }
                
            } catch let error as NSError {
                print("InteressiRegistrazioneVC getData error: \(error)")
                DispatchQueue.main.async {
                 
                }
            }
            
            // aggiorno la tabella dopo aver scaricato i dati
            DispatchQueue.main.async {
              
            }
            
        }
        task.resume()
        
    }

如何显示包含复选框和标签的单元格部分的兴趣列表,如图所示?然后,当单击复选框时,收集选中的所有ID? 我使用tableview。 感谢您的帮助

iOS Swift UITableView UIBuint

评论


答:

1赞 Chandaboy 7/7/2023 #1

enter image description here这是代码,我已经在我的本地文件中使用了你的json替换它,为TopTitleHeader创建UIview(见截图),我也有附加屏幕,只需修复这些视图,你就可以开始了

class ViewController: UIViewController {

    var feedbackArrayRec: [Interessi]?
    @IBOutlet weak var tblview: UITableView?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let object = showModeObject()
        self.feedbackArrayRec = object?.interessi
        
        self.tblview?.register(UINib.init(nibName: "TopTitleHeader", bundle: nil), forHeaderFooterViewReuseIdentifier: "TopTitleHeader")
        self.tblview?.register(UINib.init(nibName: "InteresseCell2", bundle: nil), forCellReuseIdentifier: "InteresseCell2")
        
        self.tblview?.reloadData()
    }
}

extension ViewController:UITableViewDelegate{
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        
        return 44.0
    }
    
    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?{
        
        let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "TopTitleHeader") as? TopTitleHeader
        
        let contnetView = self.feedbackArrayRec?[section].categoria
        headerView?.setContent(content: contnetView)
        return  headerView
    }
    
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 54.0
    }
    
    func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return .leastNonzeroMagnitude
    }
}


extension ViewController:UITableViewDataSource{
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
        return self.feedbackArrayRec?[section].elenco.count ?? 0
    }
    
    func numberOfSections(in tableView: UITableView) -> Int {
        return self.feedbackArrayRec?.count ?? 0
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "InteresseCell2", for: indexPath) as! InteresseCell2
        
        let objectValue = self.feedbackArrayRec?[indexPath.section].elenco[indexPath.row]
        cell.setContentValue(contnet: objectValue)
        return cell
    }
}

func showModeObject() -> EventsRecords?
{
    var tmpRec: EventsRecords?
    
    if let path = Bundle.main.path(forResource: "fatca", ofType: "json")
    {
        do {
            let jsonData = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
            let decoder = JSONDecoder()
            do {
                let people = try decoder.decode(EventsRecords.self, from: jsonData)
                tmpRec = people
            } catch {
                print(error)
            }
        }
        catch {
            // handle error
        }
    }
    
    return tmpRec
}

struct EventsRecords: Codable {
    let success: Int?
    let interessi: [Interessi]?
}

// MARK: - Interessi
struct Interessi: Codable {
    let cid, categoria: String?
    let elenco: [Elenco]
}

// MARK: - Elenco
struct Elenco: Codable {
    let id, cid, descrizione: String?
}

TopTileHeaderView

class TopTitleHeader: UITableViewHeaderFooterView {

    /*
    // Only override draw() if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func draw(_ rect: CGRect) {
        // Drawing code
    }
    */
    
    @IBOutlet weak var lblTxt: UILabel?
    @IBOutlet weak var bgColor: UIView?

    func setContent(content: String?)
    {
        self.lblTxt?.text = content
    }
}

您的 InterseCell2 类

class InteresseCell2: UITableViewCell {

    @IBOutlet weak var checkBoxInteresse: CheckBoxButton!
       
       @IBOutlet weak var labelInteresse: UILabel!
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }
    
    func setContentValue(contnet: Elenco?)
    {
        self.labelInteresse.text = contnet?.descrizione
    }
}

class CheckBoxButton: UIButton {

    // Images
    let checkedImage = UIImage(named: "check")! as UIImage
    let uncheckedImage = UIImage(named: "Uncheck")! as UIImage
    
    // Bool property
    var isChecked: Bool = false {
        didSet{
            if isChecked == true {
                self.setImage(uncheckedImage, for: .normal)
            } else {
                self.setImage(checkedImage, for: .normal)
            }
        }
    }
    
    override func awakeFromNib() {
        self.isUserInteractionEnabled = true
        self.addTarget(self, action: #selector(CheckBoxButton.buttonClicked), for: .touchUpInside)
                self.isChecked = false
    }
    
    @objc func buttonClicked(sender: UIButton) {
        if sender == self {
            if isChecked == true {
                isChecked = false
            } else {
                isChecked = true
            }
        }
    }

}

enter image description here

enter image description heretack.imgur.com/GGivh.jpg

评论

0赞 Cristian Capannini 7/7/2023
我的天啊!!谢谢@Chandaboy我会尝试的!
0赞 Cristian Capannini 7/8/2023
将我的 JSON 输入放在哪里?这里?if let path = Bundle.main.path(forResource: “fatca”, ofType: “json”) ?
0赞 Chandaboy 7/8/2023
只需将文件放入您的项目中即可。这是示例JSON文件
0赞 Cristian Capannini 7/8/2023
嗯,我没有文件,但 json 是从后端 php 给出的,我使用了代码中添加的函数 getData() @chandaboy
0赞 Cristian Capannini 7/8/2023
我已将源代码粘贴到粘贴箱 pastebin.com/M8KaSvpA 中。对象返回 nil