JSON не загружается в представлении таблицы - PullRequest
0 голосов
/ 05 июля 2018

Это мой контроллер представления с табличными представлениями

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 в табличное представление, и оно не работает. Я не вижу, что не так с моим кодом в данный момент. Если вы можете помочь, то я был бы признателен. Я также искал онлайн помощь, но не смог получить какую-либо помощь в связи с моей проблемой.

Ответы [ 3 ]

0 голосов
/ 05 июля 2018

Как следует из ответа Гусина, вам нужно заменить

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
}
0 голосов
/ 05 июля 2018

Я рекомендую использовать протокол 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 и исказить ключ .

0 голосов
/ 05 июля 2018

Эта строка if let articlesFromJSON = json["Articles"] as? [[String: Any]] { должно быть

if let articlesFromJSON = json["articles"] as? [[String: Any]] {
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...