Any reason we must fetch full list of models ahead instead of allowing each section controller to fetch data individually
New issue checklist
- [x] I have reviewed the
READMEand 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
-
IGListKitversion: - 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
}
}