IGListKit icon indicating copy to clipboard operation
IGListKit copied to clipboard

Any reason we must fetch full list of models ahead instead of allowing each section controller to fetch data individually

Open seanliu1 opened this issue 5 years ago • 0 comments

New issue checklist

  • [x] I have reviewed the README and documentation
  • [x] I have searched existing issues and this is not a duplicate
  • [x] I have attempted to reproduce the issue and include an example project.

General information

  • IGListKit version:
  • iOS version(s): Any
  • CocoaPods/Carthage version: Any
  • Xcode version: Any

I was looking at all examples, I noticed that we always try to provide a list of full models in func objects(for listAdapter: ListAdapter) -> [ListDiffable] {

In case we want to build something very similar to Instgram. Can we just build a list of ListDiffable which only contains post id, then in the section controller, we use the post id to fetch and observe actual post model change from cache or db.

So section controller is responsible to retrieve model, create immutable view model, listen for any change. If anything is changed by other parts of app (follow like etc), the change will automatically reflect if we use announcer and listener pattern without triggering adapter.performUpdates for entire lists.

I feels like that data layer holds the single source of truth, and we only need to do whole lists of diffing if we reorder, insert, delete, refresh the collection view etc. If we only update one cell (increment like count or follow), we can directly listen to the data model change from change, then update view accordingly.

The current pattern I found is that we also trigger adapter.performUpdate(), which seems pretty heavy. The only downside is that before we initially load the collection view, we need to make sure all posts model are in the cache already. Do I miss anything?

One example would be https://github.com/rnystrom/IGListKit-Binding-Guide/blob/7c5de1e648e4d26e8deb2c0c41c3e5958ca835d6/ModelingAndBinding/ModelingAndBinding/PostSectionController.swift

We can change to

struct Post {
   let postID:String
}
struct PostViewModel { 
  // all fields required by collectionViewCell
}

final class PostSectionController: ListSectionController, ListenerDelegate {
     let dataProvider:DataProvider // a dictionary or nscache or even coredata

    override func didUpdate(to object: Post) {
        post = object
    }

    override func numberOfItems() -> Int {
        return 1
    }

    override func cellForItem(at index: Int) -> UICollectionViewCell {
        guard let context = collectionContext, let viewModel = viewModel, let cell = context.dequeueReusableCell(of:PostCell.self, withReuseIdentifier: of:PostCell.reuseIdentifier, for: self, at: index) as? of:PostCell else {
            fatalError()

        }
        let postViewModel =  dataProvider.getViewModel(id:post.id) 
        dataProvider.addListener(self, postId:post.id)
        cell.viewModel = postViewModel
        return cell
    }
 
   func dataProviderDidUpdate(postViewModel) {
      let cell = collectionContext?.cellForItem(at: index, sectionController: self) as? of:PostCell
      cell.postViewModel = postViewModel // we can even have more granular animation  
   }
}

seanliu1 avatar Sep 09 '20 06:09 seanliu1