JSON 未加载到表视图中
Posted
技术标签:
【中文标题】JSON 未加载到表视图中【英文标题】:JSON isn't loading in the Table view 【发布时间】:2018-07-05 07:03:37 【问题描述】:这是我的带有表格视图的视图控制器
class HomeVC: UIViewController, UITableViewDelegate, UITableViewDataSource
private let myArray: NSArray = ["First", "Second", "Third"]
private var myTableView: UITableView!
var articles: [ArticleClass]? = []
override func viewDidLoad()
super.viewDidLoad()
view.backgroundColor = UIColor.white
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.title = "Home"
getData()
let barHeight: CGFloat = UIApplication.shared.statusBarFrame.size.height
let displayWidth: CGFloat = self.view.frame.width
let displayHeight: CGFloat = self.view.frame.height
myTableView = UITableView(frame: CGRect(x: 0, y: barHeight, width: displayWidth, height: displayHeight - barHeight))
myTableView.dataSource = self
myTableView.delegate = self
myTableView.register(ArticleCell.self, forCellReuseIdentifier: "MyCell")
view.addSubview(myTableView)
myTableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
myTableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
myTableView.topAnchor.constraint(equalTo: view.topAnchor, constant: 20).isActive = true
myTableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
func getData()
let theURL = URL(string: "https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=34e81be767734526b224ac353b1378e8")
let task = URLSession.shared.dataTask(with: theURL!) (data, response, error) in
if error != nil
print(error)
return
else
self.articles = [ArticleClass]()
do
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject]
if let articlesFromJSON = json["Articles"] as? [[String: Any]]
for articleOutOfJSON in articlesFromJSON
let theArticle = ArticleClass()
if let title = articleOutOfJSON as? String, let author = articleOutOfJSON["author"] as? String, let desc = articleOutOfJSON["description"] as? String, let url = articleOutOfJSON["url"] as? String, let imageToURL = articleOutOfJSON["imageToURL"] as? String
theArticle.theDescription = desc
theArticle.author = author
theArticle.imageURL = imageToURL
theArticle.url = url
//Putting the articleOutOfJSON into our array.
self.articles?.append(theArticle)
//Making the data be on the main thread.
DispatchQueue.main.async
self.myTableView.reloadData()
catch
print(error)
task.resume()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return 1
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! ArticleCell
cell.title.text = self.articles?[indexPath.item].headline
cell.theDesc.text = self.articles?[indexPath.item].theDescription
cell.author.text = self.articles?[indexPath.item].author
cell.theImageView.downloadImage(from: (self.articles?[indexPath.item].url)!)
return cell
func numberOfSections(in tableView: UITableView) -> Int
return self.articles?.count ?? 0
这是我的表格视图单元格。
class ArticleCell: UITableViewCell
let title: UILabel =
let label = UILabel()
label.text = "Title"
label.translatesAutoresizingMaskIntoConstraints = false
return label
()
let theDesc: UILabel =
let label = UILabel()
label.text = "TEXT TEXT TEXT TEXT TEXT TEXT"
label.translatesAutoresizingMaskIntoConstraints = false
return label
()
let author: UILabel =
let label = UILabel()
label.text = "Author"
label.translatesAutoresizingMaskIntoConstraints = false
return label
()
let theImageView: UIImageView =
let image = UIImageView()
image.backgroundColor = UIColor.purple
image.translatesAutoresizingMaskIntoConstraints = false
return image
()
override func awakeFromNib()
super.awakeFromNib()
contentView.addSubview(theImageView)
theImageView.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 8).isActive = true
theImageView.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -146).isActive = true
theImageView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 30).isActive = true
theImageView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -26).isActive = true
contentView.addSubview(title)
contentView.addSubview(theDesc)
contentView.addSubview(author)
override func setSelected(_ selected: Bool, animated: Bool)
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
这是我的数据模型。
class ArticleClass: NSObject
var headline: String?
var theDescription: String?
var author: String?
var url: String?
var imageURL: String?
var publishingDate: Int?
我尝试将 JSON 加载到我的表格视图中,但它不起作用。我目前看不出我的代码有什么问题。如果您能提供帮助,我将不胜感激。我也在网上寻求帮助,但根据我遇到的问题无法获得任何帮助。
【问题讨论】:
欢迎来到 ***。请发布文字,而不是图片 您是否在Articles
对象中获取数据?
只需使用代码更新您的帖子。谢谢。
在self.myTableView.reloadData()
设置断点并像@DharmeshKheni 所说的那样检查你的self.articles
检查关键访问文章,应该是文章
【参考方案1】:
我推荐使用Decodable
协议来解析JSON。
首先你不需要继承自NSObject
的类,结构体就足够了。文章结构使用 JSON 键作为属性:
struct News : Decodable
let status : String
let articles : [Article]
struct Article : Decodable
let description: String?
let author: String?
let url: URL
let urlToImage: URL?
let publishedAt: Date
然后将数据源数组声明为非可选
var articles = [Article]()
然后解析JSON
func getData()
let theURL = URL(string: "https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=••••••••••••••••••••")
let task = URLSession.shared.dataTask(with: theURL!) (data, response, error) in
if error != nil
print(error!)
return
else
do
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let news = try decoder.decode(News.self, from: data!)
self.articles = news.articles
//Making the data be on the main thread.
DispatchQueue.main.async
self.myTableView.reloadData()
catch
print(error)
task.resume()
您的代码中还有其他问题:
您混淆了numberOfSections
和numberOfRowsInSection
。在numberOfSections
中返回1或者省略方法
func numberOfSections(in tableView: UITableView) -> Int
return 1
在numberOfRowsInSection
返回文章数
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return articles.count
在cellForRow
中使用.row
而不是.item
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! ArticleCell
let article = self.articles[indexPath.row]
cell.title.text = article.title
cell.theDesc.text = article.description
cell.author.text = article.author
cell.theImageView.downloadImage(from: article.url)
return cell
PS:
强烈建议您不要在公共论坛上分享您的真实 API 密钥。更好的方法是发布 JSON 并乱码密钥。
【讨论】:
【参考方案2】:此行if let articlesFromJSON = json["Articles"] as? [[String: Any]]
应该是
if let articlesFromJSON = json["articles"] as? [[String: Any]]
【讨论】:
【参考方案3】:正如 Husyn 的回答中所建议的,您需要更换
if let articlesFromJSON = json["Articles"] as? [[String: Any]]
与
if let articlesFromJSON = json["articles"] as? [[String: Any]]
因为您的 Articles
密钥与来自服务器的数据不匹配,并且还有一个不匹配的密钥 imageToURL
需要根据您来自服务器的数据和您的数据替换为 urlToImage
最终代码将是:
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject]
if let articlesFromJSON = json["articles"] as? [[String: Any]]
for articleOutOfJSON in articlesFromJSON
let theArticle = ArticleClass()
if let title = articleOutOfJSON["title"] as? String, let author = articleOutOfJSON["author"] as? String, let desc = articleOutOfJSON["description"] as? String, let url = articleOutOfJSON["url"] as? String, let imageToURL = articleOutOfJSON["urlToImage"] as? String
theArticle.theDescription = desc
theArticle.author = author
theArticle.imageURL = imageToURL
theArticle.url = url
self.articles?.append(theArticle)
如果服务器将发送null
值,那么整个对象将不会附加到您的articles
对象中。所以为了更好的方式检查下面的代码:
let theArticle = ArticleClass()
theArticle.theDescription = articleOutOfJSON["description"] as? String ?? ""
theArticle.author = articleOutOfJSON["author"] as? String ?? ""
theArticle.imageURL = articleOutOfJSON["urlToImage"] as? String ?? ""
theArticle.url = articleOutOfJSON["url"] as? String ?? ""
self.articles?.append(theArticle)
numberOfRowsInSection
应该是:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return self.articles?.count ?? 0
然后删除:
func numberOfSections(in tableView: UITableView) -> Int
return self.articles?.count ?? 0
【讨论】:
以上是关于JSON 未加载到表视图中的主要内容,如果未能解决你的问题,请参考以下文章
将 customTableView 添加到未正确加载 json 数据的视图上