Swift:如何使用JSON数据动态配置具有多个部分的表格视图

时间:2019-02-06 07:25:20

标签: json swift uitableview model

我正在尝试使用从服务器上的端点检索到的JSON数据填充具有多个部分的动态UITableView。

该表视图应该显示按团队组织的用户项目列表,顶部的任何团队最多可以包含5个最新项目。

但是,由于返回了复杂的JSON,我无法在团队(节)中填充项目。我知道我必须将项目的团队ID与团队的ID进行比较,以便确定该项目是否属于该团队。但是我坚持下一步:如何存储属于团队的所有项目,然后索引此数据结构以显示部分标题的团队名称,然后显示该给定团队的项目。

到目前为止我一直在尝试做的事情:

  1. 遍历从端点获取的每个项目。
  2. 检查当前项目的团队ID是否与当前团队的ID匹配。
  3. 如果匹配,则将该项目添加到该团队中

    // Loop through each project
    for project in projects {
        // If the current project belongs to the current team
        if project.relationships.team.id == teams[section - 1].id {
            // Add the project to that team
    
        }
    
    }
    

最近的部分(顶部的第一部分)保留用于表格视图单元格列表,其中包括标题(项目的名称)和副标题(项目所在的团队)。

每个团队的表视图必须有1个部分,每个部分都显示团队的项目。表格视图单元格应包含显示项目名称的标题。

以下是端点的示例JSON响应。

我遇到的问题是弄清楚如何将每个项目分配给与其关联的团队,然后为该数据结构建立索引(我在想一个二维数组,该数组包含一组Teams,每个团队都在其中与之关联的一系列项目。

included是一组团队。 data是一系列项目。

{
  "included": [
    {
      "type": "teams",
      "id": "1",
      "attributes": {
        "name": "Team1"
      }
    },
    {
      "type": "teams",
      "id": "2",
      "attributes": {
        "name": "Team2"
      }
    },
    {
      "type": "teams",
      "id": "3",
      "attributes": {
        "name": "Team3"
      }
    }
  ],
  "data": [
    {
      "type": "projects",
      "id": "1",
      "relationships": {
        "team": {
          "id": "1",
          "type": "teams"
        }
      },
      "attributes": {
        "name": "House of Cards",
      }
    },
    {
      "type": "projects",
      "id": "2",
      "relationships": {
        "team": {
          "id": "1",
          "type": "teams"
        }
      },
      "attributes": {
        "name": "Arrested Development",
      }
    },
    {
      "type": "projects",
      "id": "3",
      "relationships": {
        "team": {
          "id": "1",
          "type": "teams"
        }
      },
      "attributes": {
        "name": "Orange Is The New Black",
      }
    },
    ...
  ]
}

我基于JSON创建了一个模型(及其关联的模型):

struct JSON: Codable {
    let included: [Included]
    let data: [Datum]
}

以下是我的代码的相关摘要:

// This should belong in the fetchData() function to be called in viewDidLoad but I believe I need access to the `section`

    var arrProjects = [Datum]()
    // Loop through each project
    for project in projects {
        // If the current project belongs to the current team
        if project.relationships.team.id == teams[section - 1].id {
            // Add the project to that team
            arrProjects.append(project)

//                let teamName = teams[section - 1].attributes.name
//                projectsByTeam.append([teamName: arrProjects])
            //projectsByTeam[section-1] = [teamName: arrProjects]

            let teamName = teams[section - 1].attributes.name
            let team = [teamName: arrProjects]
            projectsByTeam.append(team)
        }

    }


let decoder = JSONDecoder()
self?.json = try decoder.decode(JSON.self, from: data)

guard let json = self?.json else { return }

self?.teams = json.included
self?.projects = json.data

DispatchQueue.main.async { [weak self] in
    self?.tableView.reloadData()
}

...

func numberOfSections(in tableView: UITableView) -> Int {

    if let numberOfTeams = teams?.count {
        return 1 + numberOfTeams
    }

    return 1

}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    guard let projects = projects else { return 0 }
    guard let teams = teams else { return 0 }

    let numberOfProjects = projects.count

    if section == 0 {
        // Recent section
        if numberOfProjects <= 5 {
            return 0
        } else if numberOfProjects > 5 && numberOfProjects < 10 {
            return numberOfProjects - 5
        } else if numberOfProjects >= 10 {
            return 5
        }
    }

    // *NEED TO FIND THE NUMBER OF PROJECTS FOR EACH REMAINING SECTION (WHICH IS A TEAM)*
    // How to index the data structure that holds the projects for each team?

    return 0

}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    guard let project = projects?[indexPath.row] else { return UITableViewCell() }

    if indexPath.section == 0 {
        let cell = tableView.dequeueReusableCell(withIdentifier: Constants.RecentCellReuseIdentifier, for: indexPath) as! RecentTableViewCell
        cell.textLabel?.text = project.attributes.name
        cell.detailTextLabel?.text = project.relationships.team.id

        return cell
    }

    let cell = tableView.dequeueReusableCell(withIdentifier: Constants.ProjectCellReuseIdentifier, for: indexPath) as! ProjectTableViewCell
    // How to index the data structure that holds the projects for each team?
    //cell.textLabel?.text = projectsByTeam?[indexPath.section][indexPath.row]

    return cell
}

这是tableview结构的大致外观:

  

第0部分-最近

     
      
  • ProjectA(团队1)
  •   
  • ProjectD(团队2)
  •   
  • ProjectE(第3小组)
  •   
     

第1部分-第1小组

     
      
  • ProjectA
  •   
  • ProjectB
  •   
     

第2部分-第2组

     
      
  • ProjectC
  •   
  • ProjectD
  •   
     

第3节-第3组

     
      
  • ProjectE
  •   
  • ProjectF
  •   

1 个答案:

答案 0 :(得分:0)

您可以像这样构建数据结构:

var teams = [[String: [Datum]]]()
for team in teams {
let teamProjects = projects.filter {$0.relationships.team.id == team.id}
let teamData = [team: [teamProjects]]
teams.append(teamData)
}

和numberOfRows方法中的

 let team = teamsWithProjects[section-1]
 let teamProject = Array(team.values)[0]
 return teamProject.count

以及cellForRow方法中的

  let team = teamsWithProjects[indexPath.section-1]
  let teamProject = Array(team.values)[0]
  projectCell.textLabel?.text = teamProject[indexPath.row].attributes.name

希望这对您有帮助!