My TableView инициализируется до получения данных JSON. Как это предотвратить? - PullRequest
1 голос
/ 13 июля 2020

Я кодирую приложение, которое получает данные о загрязнении воздуха из API. Код передает JSON от aqicn.com. Данные обновляются слишком медленно, и сначала отображается табличное представление. Таким образом, данные для просмотра данных не отображаются. Я пробовал DispatchQueue.main.asyn c, но это не сработало. Задержки с использованием DispatchQueue.main.asyncAfter не работали. Застрял на этом уже несколько дней. Пожалуйста, дайте мне предложения или решения!

import UIKit
import MapKit

class ViewController: UIViewController, CLLocationManagerDelegate, UITableViewDataSource{
    @IBOutlet weak var tableView: UITableView!
    let searchController = UISearchController(searchResultsController: nil)
    let locationManager = CLLocationManager()
    var pm25Data:Int?
    var pm10Data:Int?

    override func viewDidLoad() {
        
        super.viewDidLoad()
        performRequest(with: "https://api.waqi.info/feed/Tainan/?token=\(C.APIkey)")
        tableView.dataSource = self
        
    }
    
    func performRequest(with typeURL: String)
    {
            if let url = URL(string: typeURL)
            {
                print("pass")
                let session = URLSession.shared
                print("pass")
                let dataTask = session.dataTask(with: url) { (data, response, error) in
                if error == nil && data != nil
                {
                    let decoder = JSONDecoder()
                    do
                    {
                        let info = try decoder.decode(AirData.self, from: data!)
                        self.pm25Data = info.data.iaqi.pm25.v
                        self.pm10Data = info.data.iaqi.pm10.v
                        DispatchQueue.main.async {
                            self.tableView.reloadData()
                        }
                    } catch
                    {
                        print("we have an error")
                    }
                    }
                }
                dataTask.resume()
            }
        
    }
    override func viewWillAppear(_ animated: Bool) {
        tableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "cellId")
        
    }
    override open var shouldAutorotate:Bool
    {
        return false
    }
    func didFailWithError(error: Error) {
        print(error)
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 2
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! TableViewCell

        if(indexPath.row == 0)
        {
            cell.descriptionName?
                .text = "PM 2.5"
            cell.valueNumber?.text = "\(pm25Data)"
        }
        else
        {
            cell.descriptionName?.text = "PM 10"
            cell.valueNumber?.text = "\(pm10Data)"
        }
        return cell
    }
    
}

1 Ответ

0 голосов
/ 16 июля 2020

Один из возможных способов ...

Поддерживать массив объектов, содержащих данные для каждой строки, я назову его dataArray, чтобы каждый объект в массиве содержал информация, необходимая для заполнения каждой соответствующей строки. Затем в вашей функции cellForRowAt после удаления ячейки из очереди, как вы уже реализовали, сделайте что-то вроде этого:

if indexPath.row == 0 {
    cell.descriptionName?.text = "PM 2.5"
    cell.valueNumber?.text = "\(pm25Data)"
    // Other setup unique to the first cell
} else {
    cell.descriptionName?.text = dataArray[indexPath.item - 1].description
    cell.valueNumber?.text = dataArray[indexPath.item - 1].description
    // Other setup unique to all following cells
}

Кроме того, реализуйте свой numberOfRowsInSection с одной строкой, просто return dataArray.count

Затем, когда ваш dataArray заполнится объектами, содержащими данные, вызовите self.tableView.reloadData()

В более широком, но все же упрощенном смысле:

Каждый когда вы вызываете reloadData(), происходит несколько вещей:

  1. TableView вызовет свою numberOfRowsInSection функцию
  2. TableView будет вызывать свою cellForRowAt функцию несколько раз. возвращается из numberOfRowsInSection и настраивает каждую строку индивидуально
  3. TableView будет вызывать другие функции, такие как heightForRowAt, по мере необходимости для настройки каждой строки

Некоторые вещи, которые нужно сохранить в уме:

  1. Вызов reloadData() каждый раз, когда вы хотите обновить sh tableView (например, с новыми данными)
  2. Вы действительно не устанавливаете настраивая каждую ячейку индивидуально, вы настраиваете logi c для заполнения ячеек извлеченными данными из детализированного источника (обычно массива)
  3. Все, что вам нужно сделать, это сохранить dataArray, а затем вызывать reloadData() каждый раз, когда вы хотите обновить sh tableView. Функция cellForRowAt обрабатывает заполнение каждой ячейки данными.

Полезное руководство:

https://www.youtube.com/watch?reload=9&v=VFtsSEYDNRU

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...