0

I'm almost done with this problem. This is the only thing left to solve.

this is what I am trying to parse: https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=API_KEY

sample[0].articles.count have an error of index out of range

I'm trying to populate the labels with the data I parsed. I tried this and it's only returning 1 cell.

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

ViewController.swift

import UIKit

struct News: Decodable {

    let articles: [Article]

    struct Article: Decodable {
        let title: String?
        let urlToImage: String?
        let description: String?
    }
}
class ViewController: UIViewController {

    @IBOutlet weak var table: UITableView!

    var sample = [News]()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        getJson()

        table.delegate = self
        table.dataSource = self

    }

    func getJson() {
        let urlString = "https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=e07d26ea273d41e2af174b026aea27b5"

        guard let url = URL(string: urlString) else { return }

        URLSession.shared.dataTask(with: url) { (data, response, error) in
            guard let data = data else { return }

            do {
                self.sample = [try JSONDecoder().decode(News.self, from: data)]
                print(self.sample[0].articles.count)
                for dict in self.sample {
                    for sam in dict.articles {
                        print(sam.title!)
                    }
                }

                DispatchQueue.main.async {
                    //reload tableView data
                    self.table.reloadData()
                }

            } catch let jsonErr {
                print("json error: ", jsonErr)
            }
        }.resume()
    }
}

extension ViewController: UITableViewDataSource, UITableViewDelegate {

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

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return CGFloat(100)
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell") as! TableViewCell
        let json = sample[0].articles[indexPath.row]
        cell.name.text = "\(json.title!)"
        cell.link.text = "\(json.description!)"
        cell.imageUrl.text = "\(json.urlToImage!)"
        return cell
    }


}
1
  • 1
    I feel this is something to do with you making sample an array of News objects, but News should (probably) be only a single object as it has the array of Articles. Commented Jun 9, 2019 at 15:29

1 Answer 1

1

You are setting sample asynchronously, tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) is called before sample contains anything. The following change will prevent the crash.

  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return sample.first?.articles.count ?? 0
    }
Sign up to request clarification or add additional context in comments.

1 Comment

Or return sample.first?.articles.count ?? 0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.