如何在swift中将json数据解析为动态集合视图节和单元格

如何在swift中将json数据解析为动态集合视图节和单元格,json,swift,sorting,dictionary,uicollectionview,Json,Swift,Sorting,Dictionary,Uicollectionview,这是我发出网络请求后从邮递员那里得到的json响应 [ { "employeeName": "Find a Sub ", "startDate": "2020-02-25", "startTime": "09:00:00", "endTime": "16:00:00" }, { "employeeName": "Find a Sub ", "startDate": "20

这是我发出网络请求后从邮递员那里得到的json响应

[
    {
        "employeeName": "Find a Sub ",
        "startDate": "2020-02-25",
        "startTime": "09:00:00",
        "endTime": "16:00:00"   
    },

   {
        "employeeName": "Find a Sub ",
        "startDate": "2020-02-25",
        "startTime": "09:00:00",
        "endTime": "16:00:00"
    },

{
        "employeeName": "Find a Sub ",
        "startDate": "2020-02-25",
        "startTime": "09:00:00",
        "endTime": "16:00:00"
    },

{
        "employeeName": "Find a Sub ",
        "startDate": "2020-02-24",
        "startTime": "09:00:00",
        "endTime": "16:00:00"  
    },

{ 
        "employeeName": "Find a Sub ",
        "startDate": "2020-02-24",
        "startTime": "09:00:00",
        "endTime": "16:00:00"     
    }]
这是我解析json数据的模型结构

struct jobsData:Decodable
{
    let employeeName:String?
    let startTime:String?
    let endTime:String?
    var startDate:String?

    init(employeeName:String?=nil,
         startTime:String?=nil,
         endTime:String?=nil,
         startDate:String?=nil){

        self.employeeName=employeeName
        self.startTime=startTime
        self.endTime=endTime
        self.startDate=startDate
    }}
我使用json解码器来解码urlSession请求之后的数据 现在,我需要以这样一种方式操纵响应:uicollectionview的节数将是startDate,其标题文本将是其文本,例如,在上述情况下,uicollectionview将有两个节。每个部分的项目将是json响应中与该日期对应的对象的数量,就像上面的情况一样,在日期为2020-02-25的部分中有三个项目,在日期为2020-02-24的部分中有两个项目。我遇到的问题是,我不知道每个部分的节数和项数,因为数据是来自api的动态数据。我如何操作json响应以将它们附加到uicollectionview中,如我所述。 这个链接很有用,但我不知道如何对数据进行排序,因为在上面的链接中只有两个键,一个用于排序,另一个用于collectionview数据,但我有多个键

编辑: 这是我的collectionview数据源函数。如何在不同部分显示数据

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)as! AvailableJobsCell
    let sTime=self.timeInAmPm(String: UserInformation[indexPath.item].startTime!)
    let eTime=self.timeInAmPm(String: UserInformation[indexPath.item].endTime!)
    cell.jobAddedTime.text="\(sTime) - \(eTime)"
    cell.jobTitle.text=UserInformation[indexPath.item].employeeName!
    cell.schoolName.text="\(UserInformation[indexPath.item].organizationName ?? "")\n\(UserInformation[indexPath.item].organizationAddress ?? "")"
    cell.jobNo.text=UserInformation[indexPath.item].confirmationNumber!
    cell.personOnHiatus.text=UserInformation[indexPath.item].positionDescription!
    cell.index=indexPath
    cell.delegate=self
        return cell
}

UserInformation的类型为[JobsData]

首先,使用大写名称声明结构,使用非可选成员,并且不使用
init
方法

struct JobsData : Decodable
{
    let employeeName : String
    let startTime : String
    let endTime : String
    var startDate : String
}
要对数据进行分组,请声明一个
结构

struct Section
{
    let title : String
    let jobsData : [JobsData]
}
并声明数据源数组

var sections = [Section]()
在解码数组之后

let jobsDataArray = try JSONDecoder().decode([JobsData].self, from: data)
使用
字典(分组:按:)
将其映射到
数组,并对其进行排序

let grouped = Dictionary(grouping: jobsDataArray, by: {$0.startDate})
self.sections = grouped.map{Section(title: $0.key, jobsData: $0.value)}
                      .sorted{$0.title < $1.title}

要显示节,请实现数据源方法

override func numberOfSections(in collectionView: UICollectionView) -> Int
    return sections.count
}


override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
    return sections[section].jobsData.count
}

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! AvailableJobsCell
    let jobData = sections[indexPath.section].jobsData[indexPath.item]
    let sTime = self.timeInAmPm(String: jobData.startTime)
    let eTime = self.timeInAmPm(String: jobData.endTime)
    cell.jobAddedTime.text = "\(sTime) - \(eTime)"
    cell.jobTitle.text = jobData.employeeName
    cell.schoolName.text = "\(jobData.organizationName ?? "")\n\(jobData.organizationAddress ?? "")"
    cell.jobNo.text = jobData.confirmationNumber!
    cell.personOnHiatus.text = jobData.positionDescription!
    cell.index = indexPath
    cell.delegate = self
    return cell
}

我使用的是swift 5.2和Xcode 11I,当我试图声明节结构“使用未声明的类型‘JobsData’”时,出现了一个错误。如何解决此问题正如我所说,请按照答案中的建议,以大写字母开头声明结构
JobsData
。感谢您的帮助。我已经编辑了我的问题。现在,我如何使用部分中的数据在uicollectionview的不同部分中显示它。我在上面添加了uicollectionview数据源函数,请参见更新。请遵守命名惯例。变量、函数、属性、枚举大小写和参数标签以小写字母开头。结构、类、枚举以大写字母开头。非常感谢。成功了。你能给我推荐一些网站或书籍,介绍我如何改进这些缺点,比如解析json和根据需要更改json,以及如何使数据源函数动态化。
override func numberOfSections(in collectionView: UICollectionView) -> Int
    return sections.count
}


override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
    return sections[section].jobsData.count
}

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! AvailableJobsCell
    let jobData = sections[indexPath.section].jobsData[indexPath.item]
    let sTime = self.timeInAmPm(String: jobData.startTime)
    let eTime = self.timeInAmPm(String: jobData.endTime)
    cell.jobAddedTime.text = "\(sTime) - \(eTime)"
    cell.jobTitle.text = jobData.employeeName
    cell.schoolName.text = "\(jobData.organizationName ?? "")\n\(jobData.organizationAddress ?? "")"
    cell.jobNo.text = jobData.confirmationNumber!
    cell.personOnHiatus.text = jobData.positionDescription!
    cell.index = indexPath
    cell.delegate = self
    return cell
}