使用Decodable将JSON解析为具有数组内部数组的TableView节

时间:2019-10-26 01:16:48

标签: ios json swift uitableview decodable

我正在尝试将来自api的数据解析为具有Sections的tableView。最终结果将是与一个月份相对应的栏目标题,以及带有该月发布的视频列表的行。这些视频可能不包含海报或说明。

我尝试实现for in循环功能以在检索数据后更新模型,这种方法一直有效,直到我开始尝试实现部分为止。我可以将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]数组中。

1 个答案:

答案 0 :(得分:1)

您可以尝试

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

}