【发布时间】: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的方法。那时,它是空的。 -
现在它不会抛出错误但表格视图不显示数据
标签: ios swift tableview codable