0

I was seeing a code where a collection view is made and we can mark some items as favorite. Also there is a filter button on top if we select that only favorite items will be visible.

Now is favorite filter is applied, then any random item is unfavourated then from the collection view, the last item disappears (which is wrong, but the bussiness logic going on is right I have tested multiple times using breakpoints) and now if I go back and come to favorites page again then the wrong item which disappeared is in the list and the correct item which was unfavorited is not present because the businesses logic was right and the data source has correct elements so the collection view made is correct (what i think).

Now I guess after tapping favorite button something wrong is hapenning, that the collection view reloading has some problem.

Also second question is is always mandatory to call

collectionView.reloadData()

and

collectionView.reloadItems(at: [IndexPath(item: index, section: 0)])

in main thread using DispatchQueue.main.async

I am new to swift, can you help out what could be the case that the reload is happening is wrong but in data source correct element is removed.


Problem gif: View Here
I was not able to add in this post

UPDATE: added code snippets:

On tapping heart symbol this function is invoked:

func editFavouriteChannelList(with viewModel: MyChannelViewModel?, index: Int) {
        guard var viewModel = viewModel,
              viewModel.isFavouriteEnabled,
              var channel = viewModel.channels?[safe: index],
              !channel.state.isChangingStateInProgress() else {
                  return
              }
        // Some working
        // Calls updateCell fn with same viewModel but updated channel state
        self.updateCell(with: viewModel, channelCellModel: channel)

        // This makes API call then again we call on it's success updateCell fn with viewModel have removed that updated channel
        interactor.editFavouriteChannelList(with: channel, isMarkingFavourite: isMarkingFavourite)
        
    }

This presenter's updateCell is called twice, first when only channelCellModel is updated and second time after making an API call that time viewModel will have that channel removed from it.

In presenter:

    private func updateCell(with viewModel: MyChannelViewModel, channelCellModel: MyChannelCellModel) {
         DispatchQueue.main.async { [weak self] in
            self.interface?.updateCell(with: viewModel, channelCellModel: channelCellModel)
         }
    }

In ViewController:

    func updateCell(with viewModel: MyChannelViewModel, channelCellModel: MyChannelCellModel) {
        if myChannelVM?.channels?.count != viewModel.channels?.count {
            self.myChannelVM = viewModel
            collectionView.reloadData()
        } else {
            guard let index = myChannelVM?.channels?.firstIndex(of: channelCellModel) else {
                return
            }
            myChannelVM?.channels?[index] = channelCellModel
            print(" Like: updateCell local : \(myChannelVM?.channels?[index])")
            collectionView.reloadItems(at: [indexPath])
        }
    }

In View Controller logic going on is like this first call to updateCell is made where viewModel is same as myChannelVM but channelCellModel is a channel with updated state.

Then second time call to updateCell is made where viewModel is same as myChannelVM but not having that channel which was earlier marked unfavorite.

Now if I remove collectionView.reloadItems(at: [indexPath]) from else block and use collectionView.reloadData() in place of it then collection view updates correctly otherwise not.

So updateCell(at:) is interfereing with reloadData() of when made in next call.

So there is issue like Why is a call to reloadItems(at:) stopping/breaking call to reloadData() in Collection View?

What is the reason for this in my case?

sac
  • 11
  • 1
  • Please, provide all relevant code snippets regarding your main question. It's impossible to figure out what's wrong with code without seeing the code. – lazarevzubov Jan 05 '23 at 05:02
  • Also, please limit one SO post to one question. However, I don't think asking a separate question about `DispatchQueue.main.async` is necessary, because SO already has plenty of information about it. Here's some: https://stackoverflow.com/questions/50727122/swift-threading-when-to-use-dispatchqueue-main-async, https://stackoverflow.com/questions/44324595/difference-between-dispatchqueue-main-async-and-dispatchqueue-main-sync, https://stackoverflow.com/questions/64126851/how-to-properly-use-dispatchqueue-main-async. – lazarevzubov Jan 05 '23 at 05:05
  • @lazarevzubov one thing I have noticed is that after running this statement `collectionView.reloadItems(at: [indexPath])`, in next line `collectionView.reloadData()` does not get invoked. The collection is not updated correctly as `setData` method for each cell is not called thus reloading is not happening. Are there any specific reasons for it? If I remove first line then reload is happening correctly `setData` for each cell of collection view is called – sac Jan 05 '23 at 05:20

0 Answers0