Как отобразить tableView только после получения данных из Интернета?(Swift) - PullRequest
0 голосов
/ 19 февраля 2019

Я столкнулся с трудностями при загрузке представлений коллекции, вложенных в ячейки табличного представления.Содержимое внутри ячеек будет отображаться только после прокрутки таблицы пару раз.Мой подход состоял в том, чтобы использовать DispatchGroup() для извлечения данных в фоновом потоке, но это не сработало.Что нужно сделать, чтобы показать всю информацию сразу, без прокрутки таблицы?

ViewDidLoad

override func viewDidLoad() {

    super.viewDidLoad()

    _tableView.isHidden = true
    _tableView.dataSource = nil
    _tableView.delegate = nil
    SVProgressHUD.show()
    view.backgroundColor = UIColor.flatBlack()

    getData()

    dispatchGroup.notify(queue: .main) {
        SVProgressHUD.dismiss()
        self._tableView.isHidden = false
        self._tableView.dataSource = self
        self._tableView.delegate = self
        self._tableView.reloadData()

    }
}

UICollectionView и UITableView источник данных / OtherMethods

func getData(){

        dispatchGroup.enter()

        backend.movieDelegate = self

        backend.actorDelegate = self

        backend.getMoviePopularList()

        backend.getMovieTopRatedList()

        backend.getMovieUpcomingList()

        backend.getPopularActors()

        backend.getMovieNowPlayingList()

        dispatchGroup.leave()
    }


    func transferMovies(data: [String:[MovieModel]]) {
        dispatchGroup.enter()
        popularMovies = data
        dispatchGroup.leave()
    }

    func transferActors(data: [ActorModel]) {
        dispatchGroup.enter()
        popularActors = data
        dispatchGroup.leave()

    }



    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        guard let cell = tableView.dequeueReusableCell(withIdentifier: "DiscoverCell") as? DiscoverViewCell else { return UITableViewCell()}

        cell.categoryLabel.text = cell.categories[indexPath.item]
        //categories[indexPath.item]
        cell._collectionView.delegate = self
        cell._collectionView.dataSource = self
        cell._collectionView.tag = indexPath.row
        cell._collectionView.reloadData()

        self.setUpCell(cell)

        return cell
    }


    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MovieCell", for: indexPath) as? MovieCollectionViewCell else { return UICollectionViewCell()}

        if collectionView.tag == 0{

            if let movieDetails = popularMovies["Popular"]?[indexPath.item] {
                cell.updateMovieCollectionCell(movie: movieDetails)
            }
        } else if collectionView.tag == 1{

            if let movieDetails = popularMovies["Top rated"]?[indexPath.item] {

                cell.updateMovieCollectionCell(movie: movieDetails)
            }
        } else if collectionView.tag == 2{

            if let movieDetails = popularMovies["Upcoming"]?[indexPath.item] {

                cell.updateMovieCollectionCell(movie: movieDetails)

            } else if collectionView.tag == 3{

                cell.movieTitleLabel.text = popularActors?[indexPath.item].name ?? ""
                cell.moviePicture.image = popularActors?[indexPath.item].poster

            }
        } else if collectionView.tag == 4{

            if let movieDetails = popularMovies["Now playing"]?[indexPath.item] {
                cell.updateMovieCollectionCell(movie: movieDetails)
            }

        }

        return cell
    }

MovieCollectionViewCell

class MovieCollectionViewCell: UICollectionViewCell {

        @IBOutlet weak var moviePicture: UIImageView!
        @IBOutlet weak var movieTitleLabel: UILabel!

        func updateMovieCollectionCell(movie: MovieModel){
            moviePicture.image = movie.poster
            movieTitleLabel.text = movie.name
        }

    }

DiscoverViewCell

class DiscoverViewCell: UITableViewCell {

        @IBOutlet weak var categoryLabel: UILabel!
        @IBOutlet weak var _collectionView: UICollectionView!

        let categories = ["Popular", "Top Rated", "Upcoming", "Popular People", "Now playing"]

        @IBAction func seeMoreAction(_ sender: Any) {

        }
    }

Я намерен показатьзагрузка анимации до тех пор, пока все данные не будут выбраны, и отобразятся ячейки табличного представления, содержащие представления сбора с извлеченными данными из Интернета.

При открытии приложения желаемый результат должен выглядеть следующим образом

The desired result should look like this when opening the app

Ответы [ 3 ]

0 голосов
/ 20 февраля 2019

Из того, что я могу сказать, вы используете dispatchGroup неправильно.

Подводя итог notify():

  • , он запускает связанный блок, когда все текущие в очереди блоки в группезавершены
  • блок запускается только один раз, а затем освобождается
  • если очередь группы пуста, блок запускается немедленно

Проблема, которую я вижу в том, чтов соответствии с тем, как написан ваш код извлечения, группа думает, что ее очередь пуста, когда вы вызываете notify.Таким образом, блок notify() запускается немедленно, и тогда вы видите, что ячейки заполняются только тогда, когда они перезагружаются во время прокрутки.

Есть два способа заполнить очередь dispatchGroup:

  • вызовDispatchQueue.async() и передать группу, чтобы поставить в очередь блок и связать его с группой
  • , вручную вызвать enter(), когда блок начинается, и leave(), когда он заканчивается, что увеличивает / уменьшает внутренний счетчик наgroup

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

Поскольку вы используете enter/leave, вам необходимо убедиться, что вы вызываете enter() для каждого отдельного рабочего элемента (в вашем случае асинхронные вызовы backend),и звоните leave() только тогда, когда каждый из этих рабочих элементов завершается.Я не уверен, как вы используете методы делегата, но, кажется, нет одного для каждого вызова backend, поскольку существует 5 различных вызовов и только 2 метода делегата.Это также не похоже на то, что методы делегата будут вызваны, если в бэкэнд-вызове произошла ошибка.

Я бы рекомендовал изменить вызовы backend, чтобы использовать вместо них блоки завершения, но если вы хотите придерживатьсяшаблон делегата, вот как вы можете это сделать:

func getData(){
    backend.movieDelegate = self
    backend.actorDelegate = self

    dispatchGroup.enter()
    backend.getMoviePopularList()

    dispatchGroup.enter()
    backend.getMovieTopRatedList()

    dispatchGroup.enter()
    backend.getMovieUpcomingList()

    dispatchGroup.enter()
    backend.getPopularActors()

    dispatchGroup.enter()
    backend.getMovieNowPlayingList()

    dispatchGroup.notify(queue: .main) {
        SVProgressHUD.dismiss()
        self._tableView.isHidden = false
        self._tableView.dataSource = self
        self._tableView.delegate = self
        self._tableView.reloadData()
    }
}

func transferPopularMovies(data: [MovieModel]) {
    popularMovies = data
    dispatchGroup.leave()
}

func transferTopRatedMovies(data: [MovieModel]) {
    topRatedMovies = data
    dispatchGroup.leave()
}

func transferUpcomingMovies(data: [MovieModel]) {
    upcomingMovies = data
    dispatchGroup.leave()
}

func transferActors(data: [ActorModel]) {
    popularActors = data
    dispatchGroup.leave()
}

func transferNowPlayingMovies(data: [MovieModel]) {
    nowPlayingMovies = data
    dispatchGroup.leave()
}

Не забудьте вызвать методы делегата, даже если есть ошибка, чтобы убедиться, что вызовы enter/leave сбалансированы.Если вы звоните enter чаще, чем leave, блок notify никогда не запускается.Если вы звоните leave чаще, вы терпите крах.

0 голосов
/ 20 февраля 2019

Установите эту строку в нижней части функции getData () и запустите

    self._tableView.isHidden = false
    self._tableView.dataSource = self
    self._tableView.delegate = self
    self._tableView.reloadData()

и удалите из viewdidload ()

0 голосов
/ 19 февраля 2019

Попробуйте это ... После получения ваших данных из бэкэнда и назначения для moviedetails установите ваш делегат и источник данных на self и перезагрузите таблицу.

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