Parse JSON 使用 Decodable 到 TableView 部分,数组内有数组

Parse JSON Using Decodable into TableView Sections with an Array inside an Array

我正在尝试将数据从 api 解析到带有部分的 tableView 中。最终结果将是一个与月份对应的部分标题和包含当月发布的视频列表的行。视频可能不包含海报或说明。

我尝试实现一个 for in loop 函数来在检索数据后更新模型,在我开始尝试实现部分之前效果很好。我可以将 json 响应打印到控制台并接收完整响应。

这是原始 JSON 结构的示例:

{
    "page": {
        "type": "videos",
        "sections": [{
            "title": "September",
            "videos": [{
                "title": "Some Video",
                "description": "Video Description",
                "poster": "",
                "url": "url"
            }]
        }, {
            "title": "August 2019",
            "videos": [{
                "title": "Some Video",
                "description": "",
                "poster": "Some Image",
                "url": "url"
            }, {
                "title": "Some Video",
                "description": "No Description",
                "poster"",
                "url": "url"
            }]
        }]
    }
}

这是我的模型:

struct Root: Decodable {
    let page: Page  
}

struct Page: Decodable {
    let type: String
    let sections: [VideoSection]
}

struct VideoSection: Decodable {
    let title: String
    let videos: [Video]
}

struct Video: Decodable {
    let videoTitle: String
    let videoDescription: String?
    let poster: String?
    let url: String

    enum CodingKeys: String, CodingKey {
        case videoTitle = "title"
        case videoDescription = "description"
        case poster = "poster"
        case url = "url"
    }
}

这里是可以通过解析进行的网络调用:

func getVideoData(url: String){

    guard let videoUrl = URL(string: "Video_URL") else { return }
    URLSession.shared.dataTask(with: videoUrl) { (data, response, error) in
        guard let data = data else { return }
        do {
            let decoder = JSONDecoder()
            let responseData = try decoder.decode(Root.self, from: data)

            DispatchQueue.main.async {    
                self.videoTableView.reloadData()
            }

        } catch let err {
            print("Error", err)
        }
    }.resume()
}

这是我的 tableView:

var allvideosArray = [Video]()
var allSectionsArray = [VideoSection]()
var rootArray: Root?

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

    let cell = tableView.dequeueReusableCell(withIdentifier: "customVideoCell", for: indexPath) as! CustomVideoCell

    cell.videoDescriptionPlaceholder.text = Video.CodingKeys.videoDescription.rawValue
    cell.videoTitlePlaceholder.text = Video.CodingKeys.videoTitle.rawValue
    return cell
}

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return allSectionsArray[section].title
}

func numberOfSections(in tableView: UITableView) -> Int {
    return allSectionsArray.count
}    

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return allvideosArray.count
}

当我尝试 print(responseData.page.sections.videos) 时,我收到错误消息“类型‘[VideoSection]’的值没有成员 'videos,',这让我相信问题与 [videos] 数组在 [sections] 数组中。

你可以试试

var page:Page?

let responseData = try decoder.decode(Root.self, from: data)
self.page = responseData.page 
DispatchQueue.main.async { 
    self.videoTableView.reloadData()
} 

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
    let cell = tableView.dequeueReusableCell(withIdentifier: "customVideoCell", for: indexPath) as! CustomVideoCell
    let item = page!.sections[indexPath.section].videos[indexPath.row]
    cell.videoDescriptionPlaceholder.text = item.videoDescription 
    cell.videoTitlePlaceholder.text = item.videoTitle
    return cell
}

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return page?.sections[section].title
} 

func numberOfSections(in tableView: UITableView) -> Int {
    return page?.sections.count ?? 0
}


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return page?.sections[section].videos.count ?? 0

}