iosjsonswiftuitableviewtaglist

showing tags inside tableviewcell from JSON Data


I am creating app Using Swift and i want show some tags inside UITableViewCell with JSON Parsing here is the screenshot which i want to do in my app

Here is the screen shot i want to do like this

as you see in screenshot Flat1, Flat2 is tags which i want to show inside UITableVieCell and for showing tags i have used below

This is the TagListView Which i have used

Here is my JSON Data which comes from WebService

{
  "success": "1",
  "data": [
    {
      "fk_project_surveyors_id": "1",
      "number": 1,
      "created_date": "2020-04-17 10:09:57",
      "sub_cores": [
        {
          "sub_cores_title": "Flat 1"
        }
      ],
      "signature": "img_sFZuFpUd011587136197.png",
      "name": "Sean Clancy",
      "inspections_id": "4",
      "fk_user_id": "1",
      "fk_cores_id": "12",
      "survey_date": "2020-04-12"
    },
    {
      "fk_project_surveyors_id": "1",
      "number": 2,
      "created_date": "2020-04-29 12:55:45",
      "sub_cores": [
        {
          "sub_cores_title": "Flat 1"
        },
        {
          "sub_cores_title": "Flat 2"
        }
      ],
      "signature": "img_Ptw0bvSGfR1588182945.png",
      "name": "Sean Clancy",
      "inspections_id": "6",
      "fk_user_id": "1",
      "fk_cores_id": "12",
      "survey_date": "2020-04-12"
    },
    {
      "fk_project_surveyors_id": "1",
      "number": 3,
      "created_date": "2020-05-06 06:08:11",
      "sub_cores": [
        {
          "sub_cores_title": "Flat 1"
        }
      ],
      "signature": "img_FSUTzxT4221588763291.png",
      "name": "Sean Clancy",
      "inspections_id": "7",
      "fk_user_id": "1",
      "fk_cores_id": "12",
      "survey_date": "2020-04-12"
    },
    {
      "fk_project_surveyors_id": "1",
      "number": 4,
      "created_date": "2020-06-15 04:25:16",
      "sub_cores": [
        {
          "sub_cores_title": "Flat 1"
        }
      ],
      "signature": "img_EVqcz58zN11592213116.png",
      "name": "Sean Clancy",
      "inspections_id": "8",
      "fk_user_id": "1",
      "fk_cores_id": "12",
      "survey_date": "2020-04-12"
    },
    {
      "fk_project_surveyors_id": "1",
      "number": 5,
      "created_date": "2020-06-21 11:04:56",
      "sub_cores": [
        {
          "sub_cores_title": "Flat 1"
        }
      ],
      "signature": "img_3ySNyhAjYd1592755496.png",
      "name": "ron",
      "inspections_id": "10",
      "fk_user_id": "1",
      "fk_cores_id": "12",
      "survey_date": "2020-04-12"
    },
    {
      "fk_project_surveyors_id": "1",
      "number": 6,
      "created_date": "2020-06-21 11:05:44",
      "sub_cores": [
        {
          "sub_cores_title": "Flat 1"
        }
      ],
      "signature": "img_ILSykgAIW71592755544.png",
      "name": "ron2",
      "inspections_id": "11",
      "fk_user_id": "1",
      "fk_cores_id": "12",
      "survey_date": "2020-04-12"
    }
  ],
  "message": ""
}

as you see in JSON Data each item has sub_cores array and from that sub_cores_title i want to show inside TagListView which is inside UITableViewCell

Here is my model structure which i have used to parse above JSON

public struct HistoryModel{
    var fk_user_id: String?
    var signature: String?
    var fk_cores_id: String?
    var name: String?
    var inspections_id: String?
    var fk_project_surveyors_id: String?
    var created_date: String?
    var number: String?
    var survey_date: String?
    var sub_cores: [SubCoreModelData]
    
    public init(fk_user_id: String,signature: String,fk_cores_id: String,name: String,inspections_id: String,fk_project_surveyors_id: String,created_date: String,number: String,survey_date: String,sub_cores:[SubCoreModelData]) {
        self.fk_user_id = fk_user_id
        self.signature = signature
        self.fk_cores_id = fk_cores_id
        self.name = name
        self.inspections_id = inspections_id
        self.fk_project_surveyors_id = fk_project_surveyors_id
        self.created_date = created_date
        self.number = number
        self.survey_date = survey_date
        self.sub_cores = sub_cores
    }
}

public struct SubCoreModelData{
    var sub_core_title: String?
    
    public init(sub_core_title: String?) {
        self.sub_core_title = sub_core_title
    }
}

and here is my code API call function from which i am storing data to an array

var historyData = HistoryModel

func historyAPI(){
        guard let uid = UserDefaults.standard.string(forKey: "uid") else { return }
        guard let accessToken = UserDefaults.standard.string(forKey: "accToken") else { return }
        guard let projectid = UserDefaults.standard.string(forKey: "propSurID") else { return }
        
        let params = ["user_id": uid, "access_token": accessToken,"project_surveyors_id": projectid,"cores_id": self.coreid]
        print(params)
        showHud(view: self.view, message: "Please Wait")
        AF.request(previousinspectionlist, method: .post, parameters: params).responseJSON(completionHandler: {(response) in
            switch response.result{
            case.success(let value):
                let json  = JSON(value)
                print(json)
                let data = json["data"]
                if data == []{
    
                }else{
                    self.historyData.removeAll()
                    for cat in data{
                        let fk_user_id = cat.1["fk_user_id"].stringValue
                        let name = cat.1["name"].stringValue
                        let signature = cat.1["signature"].stringValue
                        let fk_cores_id = cat.1["fk_cores_id"].stringValue
                        let inspections_id = cat.1["inspections_id"].stringValue
                        let fk_project_surveyors_id = cat.1["fk_project_surveyors_id"].stringValue
                        let created_date = cat.1["created_date"].stringValue
                        let number = cat.1["number"].stringValue
                        let survey_date = cat.1["survey_date"].stringValue


                        var arrOfItems = [SubCoreModelData]()
                        for ser in cat.1["sub_cores"] {
                            let subcore = SubCoreModelData(sub_core_title: ser.1["sub_cores_title"].stringValue)
                            arrOfItems.append(subcore)
                        }
                        self.historyData.append(HistoryModel(fk_user_id: fk_user_id, signature: signature, fk_cores_id: fk_cores_id, name: name, inspections_id: inspections_id, fk_project_surveyors_id: fk_project_surveyors_id, created_date: created_date, number: number, survey_date: survey_date, sub_cores: arrOfItems, collapsed: false))
                    }
                }
                self.tblListView.reloadData()
                dismissHud()
            case.failure(let error):
                basicErrorAlertWith(title: "Error", message: error.localizedDescription, controller: self)
                dismissHud()
            }
        })
    }

but with this code i am getting duplicate data in tableview so can anyone please tell me how to set tags to each row which has Sub Core title please help me for this

TableviewDelegate And DataSource Code

func numberOfSections(in tableView: UITableView) -> Int {
    return self.historyData.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let items = self.historyData[section].sub_cores
    return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! InspectionHistoryTableViewCell
    cell.lblName.text = historyData[indexPath.row].name
    if let number = historyData[indexPath.row].number{
        print(number)
        cell.lblNumber.text = "#\(number)"
    }
    cell.lblSurveydate.text = historyData[indexPath.row].survey_date
    let items = self.historyData[indexPath.section].sub_cores
    let item = items[indexPath.row]
    if let subcore = item.sub_core_title{
        cell.tagList.addTag(subcore)
    }
    cell.selectionStyle = .none
    return cell
}

Solution

  • It seems you are confusing your data model. It looks like for each entry in the historyData you have a section, and for each sub_cores in that history data you want a row.

    But what you really want is just one section, with historyData.count rows.

    In cellForRowAt: you are accessing the history data array with both row and section index, which will lead to a mixture of data and is highly likely to crash soon.

    So to correct your cellForRowAt:, you need to just access the history data per row index, and the clar and fill the tag view with all sub_cores.

    This should work:

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.historyData.count
    }
    
    func tableView (_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell    = tableView.dequeueReusableCell(withIdentifier: "Cell") as! InspectionHistoryTableViewCell
        let row     = indexPath.row
        let data    = historyData[row]
        
        cell.lblName.text = data.name
    
        if let number = data.number{
            print(number)
            cell.lblNumber.text = "#\(number)"
        }
        
        cell.lblSurveydate.text = data.survey_date
        let items = data.sub_cores
        cell.tagList.removeAllTags()
        for (item in items) {
            cell.tagList.addTag(item.sub_core_title)
        }
        
        cell.selectionStyle = .none
        return cell
    }