Как отобразить данные JSON из API в TableView?

#ios #json #swift #xcode #uitableview

#iOS #json #быстрый #xcode #uitableview

Вопрос:

Я получаю данные json из api и совершенно не понимаю, что мне делать дальше, чтобы передать эти данные в пользовательскую ячейку с изображением и метками, чтобы обновить пользовательский интерфейс в TableView.

Получение JSON

 import Foundation  struct Breed: Codable {  let name: String?  let origin: String?  let life_span:String?  let temperament: String?  let description: String?  let wikipedia_url: String?  let image: Image? }  struct Image: Codable {  let url: String? }  func getDataFromCatsApi() {    let url = URL(string: "https://api.thecatapi.com/v1/breeds")    let task = URLSession.shared.dataTask(with: url!) { data, _ , error in  let decoder = JSONDecoder()  if let data = data {  let breed = try? decoder.decode([Breed].self, from: data)  print (breed as Any)  } else {  print (error as Any)  }  }  task.resume() }  

Все данные напечатаны правильно.

В ViewController у меня есть табличное представление с пользовательской ячейкой.

 import UIKit  class MainVC: UIViewController {  @IBOutlet weak var tableView: UITableView!    override func viewDidLoad() {  super.viewDidLoad()  title = "Cats"  view.backgroundColor = .systemBackground  getDataFromCatsApi()    } }  extension MainVC: UITableViewDelegate, UITableViewDataSource {  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -gt; Int {  return 5  }    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -gt; UITableViewCell {  let cell = tableView.dequeueReusableCell(withIdentifier: "cell",  for: indexPath) as? CustomTableViewCell    return cell ?? CustomTableViewCell()  } }  

Класс для пользовательской ячейки. Здесь у меня есть просмотр изображений и метки для отображения данных из json.

 import UIKit  class CustomTableViewCell: UITableViewCell {  @IBOutlet weak var catImageView: UIImageView!  @IBOutlet weak var nameLabel: UILabel!  @IBOutlet weak var originLabel: UILabel!  @IBOutlet weak var addToFavButton: UIButton!  }  

Ответ №1:

Во-первых, вы ничего не возвращаете getDataFromCatsApi(). , так как это асинхронный вызов, вы должны реализовать способ получения значений либо с помощью обратного вызова, либо делегата. В этом случае обратного вызова было бы достаточно.

Затем, как только вы получите значение из вызова api, установите те значения func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) , в которых вы можете использовать cell.nameLabel.text = lt;received valuegt; и т. Д.

Ответ №2:

Прежде всего объявите необязательными только те свойства, которые могут быть nil

 struct Breed: Decodable {  let name, origin, lifeSpan, temperament, description: String  let wikipediaUrl: String?  let image: Image? }  struct Image: Decodable {  let url: String? }  

В getDataFromCatsApi поле добавить обработчик завершения

 func getDataFromCatsApi(completion: @escaping (Resultlt;[Breed],Errorgt;) -gt; Void ) {    let url = URL(string: "https://api.thecatapi.com/v1/breeds")    let task = URLSession.shared.dataTask(with: url!) { data, _ , error in  if let error = error { completion(.failure(error)); return }  let decoder = JSONDecoder()  decoder.keyDecodingStrategy = .convertFromSnakeCase  completion(Result { try decoder.decode([Breed].self, from: data!) })  }  task.resume() }  

В MainVC объявлении массива источников данных

 var cats = [Breed]()  

Заменить viewDidLoad на

 override func viewDidLoad() {  super.viewDidLoad()  title = "Cats"  view.backgroundColor = .systemBackground  getDataFromCatsApi {[unowned self] result in  DispatchQueue.main.async {  switch result {  case .success(let breed):   self.cats = breed  self.tableView.reloadData()  case .failure(let error): print(error)  }  }  }  }  

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

 extension MainVC: UITableViewDelegate, UITableViewDataSource {  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -gt; Int {  return cats.count  }    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -gt; UITableViewCell {  let cell = tableView.dequeueReusableCell(withIdentifier: "cell",  for: indexPath) as! CustomTableViewCell    let cat = cats[indexPath.row]  cell.nameLabel = cat.name  cell.originLabel = cat.origin  } }  

Загрузка изображений выходит за рамки вопроса. Существуют библиотеки, такие как SDWebImage или Kingfisher, для асинхронной загрузки и кэширования изображений.

Ответ №3:

Я прикрепил код, пожалуйста, проверьте

 extension MainVC: UITableViewDelegate, UITableViewDataSource {  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -gt; Int {  return Breed.count  }    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -gt; UITableViewCell {  let cell = tableView.dequeueReusableCell(withIdentifier: "cell",  for: indexPath) as? CustomTableViewCell  cell.nameLabel.text = Breed[indexPath.row].name // see here    return cell ?? CustomTableViewCell()  } }  

Комментарии:

1. У меня сбой из-за нуля, найденного в » var Breed: [Порода]!»