Не срабатывает DataSource при CollectionView.reloadData()

Цель: Когда пользователей нажимает кнопку, получить результат из Firebase и отрисовать его в CollectionView.

Что сейчас: При первом заходе в приложения я делаю запрос к Firebase и получаю ответ, все отрисовывается как нужно, ячейки на месте, коллекция тоже. Ячейка у меня кастомная и сделана в .xib файле. Теперь когда я реализовал логику получения другой информации, я меняю только одно слово, чтобы данные получал из firebase уже другие. В дебагере проверил, массив который в DataSource после нажатия содержит новые данные, логика отработала, но после collectionView.reloadData() ничего не происходит. Ошибок нет. Только есть не делать проверку на nil, тогда да, приложуха падает на collectionView

По дебагеру: collectionView - nil, numberOfItemsInSection - не вызывается и ячейки не обновляются (тем самым и UI не обновляется)..

Что пробовал: Код получения данных был у меня в фоновом потоке, reloadData делал в главном, убрал потоки, потому что думал проблемы с потоками - не помогло. Пытался найти решения, в основном ответы были что-то типа: " Вы пытаетесь обновить данные в фоновом потоке" или "У вас коллекция не связанная с IB" и тд, не относятся к моей проблеме.

Код: Я постараюсь выложить то, что нужно.

// метод который срабатывает при получение интерактива от пользователя, как я сказал
// до строчки с reload все работает, а после ничего не происходит
    DispatchQueue.global(qos: .userInitiated).async {
            self.db.collection(K.FStore.collectionName!)
              .order(by: "date", descending: true)
              .addSnapshotListener { (querySnapshot, error) in

              if let e = error {
                  print("Ошибка при получение карточек \(e)")
              } else {
                  self.cards = []
                  if let snap = querySnapshot?.documents {
                     for item in snap {
                        let data = item.data()
                        if let fio = data[K.FStore.fullName] as? String, let price = data[K.FStore.price] as? String, let phone = data[K.FStore.phone] as? String, let description = data[K.FStore.description] as? String, let address = data[K.FStore.address] as? String {

                          let newCard = Card(fio: fio, phone: phone, price: price, description: description, address: address, idCard: item.documentID)  
                            self.cards.append(newCard)
                         }
                      }

                    DispatchQueue.main.async {
                       self.collectionView?.reloadData()
                    }
                }
            }
        }
    }
// self.cards - это массив Card, где есть определенная информация по карточке, потом Card я сделал в Cell ( т.е. кастомная ячейка - это карточка
// UICollectionViewDataSource
 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
       return cards.count
    }

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

       let cardCell: Card

       let cell = collectionView.dequeueReusableCell(withReuseIdentifier: K.cellMainScreenIndet, for: indexPath) as! MainCellCollectionView

       cardCell = cards[indexPath.row]

       cell.fioLabel.text = cardCell.fio
       cell.priceLabel.text = cardCell.price
       cell.addressLabel.text = cardCell.address
       cell.discriptionLabel.text = cardCell.description
       cell.phoneLabel.text = cardCell.phone

       return cell
   }

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


Ответы (1 шт):

Автор решения: Андрей Хышов

Взял исходный код здесь

По порядку:

  1. collectionView nil потому что MenuViewController написано let vc: MainViewController = MainViewController(), а collectionView является @IBOutlet, если инитить из сторибоарда надо делать так
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let viewController = storyboard.instantiateViewControllerWithIdentifier("MainViewController") as? MainViewController
  1. В MenuViewController происходит управление совершенно другим инстансом MainViewController, чтобы управлять нужным MainViewController должен о себе как-то сообщить, например переопределить prepare for segue следующим образом
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let menuNavigationController = segue.destination as? SideMenuNavigationController,
            let menuViewController = menuNavigationController.viewControllers.first as? MenuViewController {
                menuViewController.mainViewController = self
        }
    }

а в MenuViewController заменить

let vc: MainViewController = MainViewController()

на

weak var mainViewController: MainViewController?
→ Ссылка