Home > OS >  Why My cells in collectionView are formed faster than the method of receiving data, for their format
Why My cells in collectionView are formed faster than the method of receiving data, for their format

Time:11-24

In my application, after authorization, the user is taken to a screen that displays news according to the specified parameters, news is transmitted through the API.

in the viewWillAppear method, the getUserSettings method is triggered, in which the fetchNewsData method is triggered, which fills an array with news, based on this array, collection cells are formed. The array is filled with actual data from the database, which contains user settings. My code is below:

class NewsViewController: UIViewController {
    
    let networkManager = NetworkManager()
    
    var newsArray = [NewsModel]()
    var totalResult:Int = 0
    var ref: DatabaseReference!
    
    @IBOutlet weak var collectionView: UICollectionView!
    
    @IBAction func settingsAction(_ sender: UIBarButtonItem) {
        performSegue(withIdentifier: "settingsSegue", sender: nil)
    }
    
    @IBAction func unwindSegueToNewsScreen(segue: UIStoryboardSegue) {
        
        guard segue.identifier == "unwindFromSettingsSegue" else { return }
    }
    
    private func getUserSettings(completion: @escaping (UserModel) -> ()) {
        guard let currentUser = Auth.auth().currentUser else { return }
        
        var user: UserModel!
        user = UserModel(user: currentUser)
        ref = Database.database().reference(withPath: "users").child(String(user.uid))
        ref.observe(.value) { snapshot in
            guard let snapshotValue = snapshot.value as? [String : String] else { return }
            user.userCountry = snapshotValue["country"]
            user.userCategory = snapshotValue["category"]
            completion(user)
        }
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        getUserSettings { [weak self] user in
            self?.networkManager.fetchNewsData(forCoutry: user.userCountry ?? "us", category: user.userCategory ?? "sports") { [weak self] newsDataModel in
                
                self?.totalResult = newsDataModel.totalResults
                
                for article in newsDataModel.articles {
                    let news = NewsModel(newsTitle: article.title,
                                         urlToNewsWebSite: article.url,
                                         authorWebSiteName: article.source.name,
                                         urlToImage: article.urlToImage ?? "" )
                    
                    self?.newsArray.append(news)
                }
                DispatchQueue.main.async {
                    self?.collectionView.reloadData()
                }
                
            }
        }
    }
    
}


extension NewsViewController: UICollectionViewDataSource {
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return newsArray.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "item", for: indexPath) as! NewsCell
        cell.configureCell()
        cell.initData(news: newsArray[indexPath.item])
        return cell
    }
}

I want to give the user the ability to change settings on an additional screen

On the second screen, the user will update their data in the database, and I want the table to load the updated data again when I return to the news screen, but I have a problem.

When the table loads data for the first time, the cell formation methods are triggered:

 func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return newsArray.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "item", for: indexPath) as! NewsCell
        cell.configureCell()
        cell.initData(news: newsArray[indexPath.item])
        return cell
    }

But due to the fact that initially the array with news is empty, cells cannot be formed. newsArray.count // = 0

But due to the fact that initially the array with news is empty, the cells cannot be formed, so then the method is launched that fills the array and reloads the cells, and now the cells are formed. But when I get to the news screen from the settings screen, the cells already have data, because the newsArray is not empty, and cells with irrelevant information are displayed on the screen.

i tried to update collection using collectionView.reloadData() but it doesn't help, also i tried this:

 override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        guard segue.identifier == "unwindFromSettingsSegue" else { return }
        let dvc = segue.destination as! NewsViewController
        dvc.collectionView.reloadData()
    }

This doesn't work because the collection is simply updated with the newsArray values that were generated before going to the settings screen

What needs to be changed to make this work correctly?

CodePudding user response:

Based on the code you posted, I'm guessing that you will need to clear the newsArray before you load content into it again. As your code is written now, you append new news to it. This would lead to you continually adding to it instead of replacing what was there.

  • Related