I have this method to put data into my dataSource array which is used for my collection view
private func fetchInitialData() {
for index in self.HITSSOURCE_CHALLENGE_COPY_COUNT..<self.challengeHitsInteractor.numberOfHits() {
if let jsonChallengeObject: Hit<JSON> = try? self.challengeHitsInteractor.hit(atIndex: index),
let challengeObject: Challenge = try? Challenge(json: jsonChallengeObject.object) {
let challengeProfileItem = ChallengeProfileItem()
challengeProfileItem.challengeObject = challengeObject
self.HITSSOURCE_CHALLENGE_COPY_COUNT = self.challengeHitsInteractor.numberOfHits()
self.dataSource.append(challengeProfileItem)
}
}
for index in self.HITSSOURCE_TOURNAMENT_COPY_COUNT..<self.tournamentHitsInteractor.numberOfHits() {
if let jsonTournamentObject: Hit<JSON> = try? self.tournamentHitsInteractor.hit(atIndex: index),
let tournamentObject: Tournament = try? Tournament(json: jsonTournamentObject.object) {
let tournamentProfileItem = TournamentProfileItem()
tournamentProfileItem.tournamentObject = tournamentObject
self.HITSSOURCE_TOURNAMENT_COPY_COUNT = self.tournamentHitsInteractor.numberOfHits()
self.dataSource.append(tournamentProfileItem)
}
}
self.eventCollectionView?.reloadData()
}^
Now, in the cellForItemAt delegate method, I am iterating through this dataSource array
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
self.hideActivityView()
let myChallengesCell = collectionView.dequeueReusableCell(withReuseIdentifier: MyEventsCollectionViewCell.reuseIdentifier, for: indexPath) as! MyEventsCollectionViewCell
myChallengesCell.delegate = self
if (self.challengeHitsInteractor.numberOfHits() + self.tournamentHitsInteractor.numberOfHits() == 0) {
return myChallengesCell
}
if self.displayedIndices.contains(indexPath.row) {
return myChallengesCell
}
else {
let abstractProfileItem = self.dataSource[indexPath.row]
self.displayedIndices.insert(indexPath.row)
myChallengesCell.indexPath = indexPath
switch abstractProfileItem.challengeType {
case .singleChallenge:
var challengeProfileItem = abstractProfileItem as! ChallengeProfileItem
challengeProfileItem = myChallengesCell.setupCellWithChallengeProfileItem(challengeObject: challengeProfileItem.challengeObject) as! ChallengeProfileItem
myChallengesCell.setEventTitle(abstractEvent: challengeProfileItem.challengeObject)
self.dataSource[indexPath.row] = challengeProfileItem
..
in my MyEventsCollectionViewCell cell, I setup some properties synchronously, however, some other data need to be fetched from the database on the fly
public func setupCellWithChallengeProfileItem(challengeObject:Challenge) -> AbstractProfileItem {
self.challengeProfileItem = ChallengeProfileItem()
self.challengeProfileItem?.delegate = self
self.setEventTitle(abstractEvent: challengeObject)
self.checkIfToAddOrRemovePlayIcon(abstractEvent: challengeObject)
self.challengeProfileItem.challengeObject = challengeObject
challengeObject.eventType = .singleChallenge
DispatchQueue.main.async {
self.challengeProfileItem.populateChallengeObject(challengeObject: challengeObject)
}
return self.challengeProfileItem
}
The ChallengeProfileItem looks like this
public func populateChallengeObject(challengeObject:Challenge) {
self.userDataAccessService.checkIfUserIsBlocked(completionHandler: { (userExists, isSourceUserBlocked, isTargetUserBlocked, userId) in
if (!userExists || isSourceUserBlocked || isTargetUserBlocked) {
return
}
else {
self.challengeParticipationDataAccessService.fetchParticipationByUserIdChallengeId(completionHandler: { (participationObject) in
self.ratingDataAccessService.fetchRatingByEventIdAndParticipantId(completionHandler: { (numberOfRating) in
self.numberOfRating = numberOfRating
self.delegate?.didFetchRating(eventType: .singleChallenge, eventId: challengeObject.id, rating: numberOfRating)
}, participantId: participationObject.userId, eventId: participationObject.challengeId)
}, userId: challengeObject.organizerId!, challengeId: challengeObject.id!)
self.challengeResourceService.identifyRankingOfParticipant(completionHandler: { (ranking, numberOfParticipants) in
self.ranking = ranking
self.numberOfParticipants = numberOfParticipants
self.delegate?.didFetchRankingAndNumberOfParticipants(eventType: .singleChallenge, eventId: challengeObject.id, ranking: ranking, numberOfParticipants: numberOfParticipants)
}, challengeId: challengeObject.id!)
self.challengeDataAccessService.fetchDownloadURLOfChallengeImage(challengeId: challengeObject.id!) { (contentURL) in
self.delegate?.didFetchContentURL(eventType: .singleChallenge, eventId: challengeObject.id, contentURL: contentURL!)
}
}
}, sourcePersonId: Auth.auth().currentUser?.uid, targetPersonId: challengeObject.organizerId!)
}
Once the data is fetched, I go back to the view with my collection view by using delegates. On the view where my collection view is located, I'll try to update the specific cell by using an index.
extension MyEventsView:MyEventsCollectionViewCellDelegate {
func didFetchContentURL(eventType: EventType, eventId: String, contentURL: URL) {
if let index = self.findIndexForEventItem(withID: eventId) {
let indexPath = IndexPath(row: index, section: 0)
DispatchQueue.main.async {
if let cell = self.eventCollectionView?.cellForItem(at: indexPath) as? MyEventsCollectionViewCell {
self.dataSource[indexPath.row].contentURL = contentURL
let challengeProfileItem = self.dataSource[indexPath.row] as! ChallengeProfileItem
print(challengeProfileItem.challengeObject.title)
print(cell.challengeTitleLabel?.text)
cell.challengeImageView!.sd_setImage(with: contentURL, placeholderImage: UIImage(named: "placeholder.png"))
}
}
}
}
It looks like, there is a mismatch of data. The displayed image doesn't match the challenge title attribute. I know cells are designed to be re-used but when I tried to reset the data within the prepareForReuse() method, the challenge title was displayed at all.
I am struggling with this issue unfortunately..