Below is the code of my ViewController
class NewsViewController: UIViewController {
let networkManager = NetworkManager()
var newsArray = [NewsModel]()
var totalResult:Int = 0
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
networkManager.fetchNewsData(forCoutry: "us", category: "business") { 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)
}
}
collectionView.reloadData()
}
}
extension NewsViewController: UICollectionViewDelegate {
}
extension NewsViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 10
}
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])
collectionView.reloadData()
return cell
}
}
I need to request data from the network, and then process them in a loop in the completion Handler, and fill the newsArray = [NewsModel]()
, and only then initialise the cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "item", for: indexPath) as! NewsCell
cell.configureCell()
cell.initData(news: newsArray[indexPath.item])
collectionView.reloadData()
return cell
But first, the cell is initialised for me, and only then the code from the completion Handler starts working, I figured it out using the breakpoint.
How can I fix this?
CodePudding user response:
You should return the length of the newsArray
here:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return newsArray.count
}
This will cause cellForItemAt
to not be called if newsArray
is empty (such as when it is initially).
Next, you should move the reloadData
call to inside the completion handler, so that cellForItemAt
is called after newsArray
has items.
networkManager.fetchNewsData(forCoutry: "us", category: "business") { [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)
}
// notice this:
self?.collectionView.reloadData()
}
CodePudding user response:
You should add the collectionView.reload data in the completionHandler (dispatch in main queue). Also, do not reload collectionView in cellForRow, because it may end up with endless loop.