【问题标题】:How to display JSON data from API in TableView?如何在 TableView 中显示来自 API 的 JSON 数据?
【发布时间】:2022-01-08 02:58:12
【问题描述】:

我从 api 收到 json 数据,完全不知道接下来应该怎么做才能将这些数据传递给带有 imageView 和标签的自定义单元格,以便更新 tableView 中的 UI。

获取 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 中,我有一个带有自定义单元格的 tableView。

    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) -> Int {
        return 5
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell",
                                                 for: indexPath) as? CustomTableViewCell
        
        return cell ?? CustomTableViewCell()
    }
}

自定义单元格的类。这里我有用于显示来自 json 数据的 imageView 和标签。

    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!

}

【问题讨论】:

    标签: ios json swift xcode uitableview


    【解决方案1】:

    我已附上代码,请检查

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

    【讨论】:

    • 由于在 'var Breed: [Breed]!' 中发现 nil 导致我崩溃了
    【解决方案2】:

    首先,你不会从getDataFromCatsApi(). 返回任何东西因为它是一个异步调用,你必须实现一种方法来通过使用回调或委托来获取值。在这种情况下,回调就足够了。

    然后,一旦您从 api 调用中收到一个值,请将这些值设置在 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) 中,您可以在其中使用 cell.nameLabel.text = <received value> 等。

    【讨论】:

      【解决方案3】:

      首先,仅将那些属性声明为可选,可以是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 (Result<[Breed],Error>) -> 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) -> Int {
              return cats.count
          }
          
          func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> 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 等库可以异步加载和缓存图像。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-12-23
        • 2021-09-12
        • 2020-03-28
        • 1970-01-01
        • 1970-01-01
        • 2020-11-04
        • 2017-03-26
        相关资源
        最近更新 更多