【问题标题】:empty tableview from loading data from json in swift 4在swift 4中从json加载数据的空tableview
【发布时间】:2018-01-04 16:17:07
【问题描述】:

所以是的,谢谢你们,我刚刚将整个代码更改为可编码为正确的 swift 4 大声笑。但是控制台仍然没有显示tableview 说: “已下载 下载时出现问题”

final let url = URL(string: "https://newsapi.org/v2/top-headlines?sources=espn&apiKey=ada86a1d56d348a29a7c7501869bac2f")
private var articles = [Article]()
@IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        downloadJson()
        tableView.tableFooterView = UIView()
    }

func downloadJson(){
            guard let downloadURL = url else {return}
            URLSession.shared.dataTask(with: downloadURL){data, URLResponse, error in
                guard let data = data, error == nil, URLResponse != nil else{
                    print("something is wrong")
                    return
                }
                print("downloaded")
                do
                {
                    let decoder = JSONDecoder()
                    let downloadedArticles = try decoder.decode(Articles.self, from: data)
                    self.articles = downloadedArticles.articles
                    DispatchQueue.main.async {
                        self.tableView.reloadData()
                    }
                }catch {
                    print("something is wrong when downloaded")
                }
            }.resume()
        }

这是来自文章可编码类

class Articles: Codable {
    let articles: [Article]

    init(articles: [Article]){
        self.articles = articles
    }
}

class Article: Codable{
    let title: String
    let description: String
    let author: String
    let image: String

    init(title: String, description: String, author: String, image: String){
        self.title = title
        self.description = description
        self.author = author
        self.image = image
        }
}

这是cellforrowat(我不能发布它,因为我的整个帖子主要是代码。哈哈):

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "ArticleCell") as? ArticleCell else {
            return UITableViewCell()}
        cell.titleLabel.text = "" + articles[indexPath.row].title
        cell.descLabel.text = "" + articles[indexPath.row].description
        cell.authorLabel.text = "" + articles[indexPath.row].author

        if let imageURL = URL(string: articles[indexPath.row].image){
            DispatchQueue.global().async {
                let data = try? Data(contentsOf: imageURL)
                if let data = data {
                    let image = UIImage(data: data)
                    DispatchQueue.main.async {
                        cell.imgView.image = image
                    }
                }
            }
        }
        return cell
    }

【问题讨论】:

  • 在某些时候,您需要调试。 article.author = author 被调用了吗?当你打电话给self.tableview.reloadData()时,articles是空的吗?

标签: json swift swift4


【解决方案1】:

您应该检查您的 json 和 articleFromJs 的调试内容。 可能articlesFromJs 为空或JSON 格式不正确。

让 json = 试试 JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [字符串:任何对象]

如果让articlesFromJson = json["articles"] 为? [[String : >AnyObject]]

也使用 Codable 代替 JSONSerialization。

【讨论】:

  • 我已将其更改为可编码类,但仍然无法正常工作哈哈。介意你检查一下吗? :)
  • 你能展示你的json文件吗?如何转换它?
【解决方案2】:

首先确保表视图的datasource(以及delegate以供将来使用)已在Interface Builder中连接。

对于表格视图,它是 indexPath.row 而不是 indexPath.item

进一步建议在cellForRow中只获取一次数据源项,并将数据源数组声明为非可选(本教程很差,提示不良习惯和知识一半)。而且 - 一如既往 - 选项 .mutableContainers 在 Swift 中毫无意义。

var articles = [Article]()

罢工>

     if let json = try JSONSerialization.jsonObject(with: data!) as? [String:Any],
        let articlesFromJson = json["articles"] as? [[String:Any]] {
        ...

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "articleCell", for: indexPath) as! ArticleCell

    let article = articles[indexPath.row]
    cell.title.text = article.headline
    cell.desc.text = article.desc
    cell.author.text = article.author
    cell.imgView.downloadImage(from: article.imageUrl!)!
    return cell
}

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

删除numberOfSections 方法。默认为1

在 Swift 3+ 中,JSON 字典是 [String : Any],而不是 [String : AnyObject]


在 Swift 4 中,考虑使用 Codable 协议将 JSON 解析为结构。方便多了。


更新:

Article 类与给定 URL 的 JSON 不匹配。将其更改为以下内容。 author 必须是可选的,并且没有密钥 image。顺便说一句,如果您采用Codable,则不需要编写初始化程序。

class Articles: Codable {
    let articles: [Article]
}

class Article: Codable {
    let title: String
    let description: String
    let author: String?
    let urlToImage: URL
}

PS:URLResponse 是一种类型。使用小写字母以避免混淆,例如dataTask(with: downloadURL) {data, response, error。但是在您的情况下,根本不需要该参数。

【讨论】:

  • 我已将其更改为可编码类,但仍然无法正常工作哈哈。介意你检查一下吗? :)
  • 啊抱歉,我错误地粘贴了我的参考代码,而不是大声笑。我已将其更改为匹配我的项目代码并添加 cellforrowat :)
  • 我再次更新了答案。解码应该可以工作。
  • 我们已经按照文章类的说明进行操作。但是如何在 cellForRowAt 中调用可选字符串和 url?我试了几次。但看来我这次搞砸了,哈哈。
  • "" + articles[indexPath.row].author 的语法很荒谬。在cellForRow 方法中——我已经介绍过了——我向你展示了将字符串值分配给标签的正确方法。关于图像:首先,URL 不是可选的,但无论如何你的方式是完全错误的。 从不使用Data(contentsOf: 从远程 URL 加载数据,并考虑在用户滚动时可以立即释放单元格。您必须使用单独的下载管理器为图像提供缓存。
猜你喜欢
  • 1970-01-01
  • 2016-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-10
  • 2018-12-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多