在表视图中使用 JSON 编码错误
Posted
技术标签:
【中文标题】在表视图中使用 JSON 编码错误【英文标题】:JSON codable error while using in Table View 【发布时间】:2020-07-07 02:31:26 【问题描述】:我正在使用 newsapi.org api 构建一个新闻应用程序。我能够从服务器获取数据并使用 JSON 解码器对其进行解码,但问题出在响应中,当我通过提供部分中的行数作为文章数组将文章数组作为数据源分配给表视图时,我得到了文章数组计数我收到一条错误消息,指出在 numberofrowsinsetction 方法中隐式展开可选值时意外发现 nil。
我能够在调试控制台中打印articles.count,目的是获取计数。但是当我将它分配给numberrowsinsection方法时,我得到了这个错误。
网络服务代码
import Foundation
class NetworkService
static let sharedobj = NetworkService()
let session = URLSession.shared
private let HEADLINES_URL = "https://newsapi.org/v2/top-headlines?country=in&apiKey=API_key_HERE"
public func getHeadLines(onSuccess: @escaping ([Articles]) -> Void)
let datatask = session.dataTask(with: URL(string: HEADLINES_URL)!, completionHandler: (data, response, error) in
DispatchQueue.main.async
do
let decoder = try JSONDecoder().decode(Welcome.self, from: data!)
onSuccess(decoder.articles!)
catch
print(error.localizedDescription)
)
datatask.resume()
查看控制器代码
import UIKit
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource
var articles: [Articles]!
var newsurl: String!
@IBOutlet weak var headlinestableview: UITableView!
override func viewDidLoad()
super.viewDidLoad()
self.headlinestableview.delegate = self
self.headlinestableview.dataSource = self
NetworkService.sharedobj.getHeadLines (a) in
self.articles = a
print(self.articles.count)
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return articles.count
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
if let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? HeadLinesCellTableViewCell
let data = articles[indexPath.row]
cell.updateCell(title:data.title ?? "Not Found", body: data.content ?? "No Body", imgurl: data.urlToImage ?? "https://en.wikipedia.org/wiki/Pages_(word_processor)#/media/File:Pages_Icon.png")
newsurl = data.url
return cell
return UITableViewCell()
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
performSegue(withIdentifier: "segue", sender: self)
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
if let destinationVC = segue.destination as? BrowserVC
destinationVC.url = newsurl
模型结构(使用 JSON 生成到 Swift 网站)
struct Welcome : Codable
let status : String?
let totalResults : Int?
let articles : [Articles]?
enum CodingKeys: String, CodingKey
case status = "status"
case totalResults = "totalResults"
case articles = "articles"
init(from decoder: Decoder) throws
let values = try decoder.container(keyedBy: CodingKeys.self)
status = try values.decodeIfPresent(String.self, forKey: .status)
totalResults = try values.decodeIfPresent(Int.self, forKey: .totalResults)
articles = try values.decodeIfPresent([Articles].self, forKey: .articles)
struct Articles : Codable
let source : Source?
let author : String?
let title : String?
let description : String?
let url : String?
let urlToImage : String?
let publishedAt : String?
let content : String?
enum CodingKeys: String, CodingKey
case source = "source"
case author = "author"
case title = "title"
case description = "description"
case url = "url"
case urlToImage = "urlToImage"
case publishedAt = "publishedAt"
case content = "content"
init(from decoder: Decoder) throws
let values = try decoder.container(keyedBy: CodingKeys.self)
source = try values.decodeIfPresent(Source.self, forKey: .source)
author = try values.decodeIfPresent(String.self, forKey: .author)
title = try values.decodeIfPresent(String.self, forKey: .title)
description = try values.decodeIfPresent(String.self, forKey: .description)
url = try values.decodeIfPresent(String.self, forKey: .url)
urlToImage = try values.decodeIfPresent(String.self, forKey: .urlToImage)
publishedAt = try values.decodeIfPresent(String.self, forKey: .publishedAt)
content = try values.decodeIfPresent(String.self, forKey: .content)
// MARK: - Source
struct Source : Codable
let id : String?
let name : String?
enum CodingKeys: String, CodingKey
case id = "id"
case name = "name"
init(from decoder: Decoder) throws
let values = try decoder.container(keyedBy: CodingKeys.self)
id = try values.decodeIfPresent(String.self, forKey: .id)
name = try values.decodeIfPresent(String.self, forKey: .name)
TableView 单元格代码
import UIKit
class HeadLinesCellTableViewCell: UITableViewCell
@IBOutlet weak var headlinesimageview: UIImageView!
@IBOutlet weak var headlinestitlelbl: UILabel!
@IBOutlet weak var headlinesbodylbl: UILabel!
func updateCell(title: String,body: String,imgurl: String)
headlinestitlelbl.text = title
headlinesbodylbl.text = body
DispatchQueue.global(qos: .userInitiated).async
if let data = try? Data(contentsOf: URL(string: imgurl)!)
if let image = UIImage(data: data)
DispatchQueue.main.async
self.headlinesimageview.image = image
【问题讨论】:
我想没有人会喜欢看到这么多空行代码。 好的,等一下我改一下 将var articles: [Articles]!
改为var articles: [Articles] = []
,在api响应文章之前调用datasource的方法。那时,它是空的。
现在它不会抛出错误但表格视图不显示数据
【参考方案1】:
而不是这个:
var articles: [Articles]!
用它来声明文章:
var articles = [Articles]()
更新:
在您的 didSelectRow
方法中执行以下操作:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
let article = articles[indexPath.row]
performSegue(withIdentifier: "segue", sender: article)
【讨论】:
@stark 您的初始化代码有问题。请检查此代码。 现在它不会抛出错误但表格视图不显示数据 另一个问题是,当我单击表格视图单元格时,它应该打开一个 Web 视图以显示新闻链接,但链接与表格视图单元格中的文章不匹配。 @Stark 如果它回答了您的原始问题,您可以投票并标记为正确答案 @stark 实现Didselectrow
方法,而不是DidDeselectrow
方法以上是关于在表视图中使用 JSON 编码错误的主要内容,如果未能解决你的问题,请参考以下文章
当我在表视图中配置它时,使用表视图 xib 常量空间正在消失
使用 Core Data 的 View Controller 中的表视图