Iglistkit: Clarity on best practices

Created on 27 Jul 2017  路  2Comments  路  Source: Instagram/IGListKit

it'd be helpful to use a real world example and share some of the concerns raised in 799, and get feedback regarding best practices to fix it.

Example

Suppose you have an instagram post, when you view the post you'll receive a JSON response from the server, and map it to a Post object, the Post class looks like this:

images: [PostImage] // an array of post images
status: Status // a post status object (not that important)
comments: [Comment] //an array of comment objects

Based on: https://github.com/Instagram/IGListKit/issues/799 , we should do the following

  • Within the post's view controller, create a flat array var objects: [ListDiffable], which may look like this: [PostImage, PostImage, Status, Comment, Comment, Comment]
  • In our view controller, implement the necessary function func listAdapter(_ listAdapter: ListAdapter, sectionControllerFor object: Any) -> ListSectionController and create section controllers for each image, each comment, and the status.
  • These section controllers should have numberOfItems always return 1 and will have the appropriate object available within them (e.g. Comment, PostImage ...)

Here's been my problem with this since approach day one:

  • It seems unintuitive that we need to build the ViewController's objects: [ListDiffable] array like follows:
    objects.append(contentsOf: post_resp.images)
    object.append(post_resp.status)
    objects.append(contentsOf: post_resp)
    ending up with objects equaling
    [PostImage, PostImage, status, Comment, Comment, Comment]

Because

  • what is the purpose of numberOfItems in the section controller? When wouldn't it be 1 if this is the pattern to follow (i.e. 1 master list with section controllers for each ListDiffable object)? If there is a use case for numberOfItems, it seems that it can't be dynamic... (see below)
  • what if the comment section needed a header like "5 comments". With this approach wouldn't you have to create a whole new section controller like "CommentHeaderListSectionController"? Because creating a supplementary header view inside the comment's section controller would present a header for each comment.

Now, a more sensible approach might be this (but ends up breaking down) :

object.append(post_resp) //in our view controller, append just the post

  • Then in func listAdapter(_ listAdapter: ListAdapter, sectionControllerFor object: Any) -> ListSectionController we would create a stacked section controller containing: PostImagesListSectionController, StatusListSectionController and CommentsListSectionController. and yield the entire post object to each section (which is also helpful if one of these sections needs to know a little more about the post, like it's id or something)

  • in a section controller with multiple items e.g. (CommentsListSectionController), you'd have numberOfItems return post.comments.count. and create collectionviewcells for each comment.

  • I could then put a supplementary view for the comments section header, and not have to create a whole new section controller for the header

Problem
This seems like a cleaner approach, but what if you need to append a comment to the array of comments? Well, since you're presumably yielding a Post object to the comments section controller, wouldn't you do post_obj.comments.append(comment) in the post's ViewController, and call performUpdates? Right now this returns the error in #799 and apparently isn't the right way to do things.

question

Most helpful comment

I'll try to summarize some thoughts before I get back from my trip, but this is actually an anti pattern we need to do a better job explaining.

Each section controller should contain logic for a single, too-level model (Post in your example). _Within_ that section controller, you can decompose the Post into an array that drives numberOfItems. Do this however you want. We have an example at the bottom of the FAQ.

Take a deeper look at our examples. We have one with _exactly_ this setup (posts, images, comments) with an architecture like I just described.

Would a tutorial or guide linked from the root readme help here? cc @jessesquires since we've gotten this question a lot.

Lastly take a look at my GitHub app. It's totally powered by IGListKit and has some very advanced stuff in there. It should give you an idea to just how powerful this framework is.

All 2 comments

I'll try to summarize some thoughts before I get back from my trip, but this is actually an anti pattern we need to do a better job explaining.

Each section controller should contain logic for a single, too-level model (Post in your example). _Within_ that section controller, you can decompose the Post into an array that drives numberOfItems. Do this however you want. We have an example at the bottom of the FAQ.

Take a deeper look at our examples. We have one with _exactly_ this setup (posts, images, comments) with an architecture like I just described.

Would a tutorial or guide linked from the root readme help here? cc @jessesquires since we've gotten this question a lot.

Lastly take a look at my GitHub app. It's totally powered by IGListKit and has some very advanced stuff in there. It should give you an idea to just how powerful this framework is.

just a follow up for anyone reading this. List binding section controller has solved all of the issues I've been having. Specifically for cases where I have something like a post object with a lot of nested objects (i.e. comments, tags, etc...) This example helped me out a lot too. https://github.com/Instagram/IGListKit/blob/master/Guides/Modeling%20and%20Binding.md

Thanks for the awesome library!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Megaman63 picture Megaman63  路  17Comments

rafalszastok picture rafalszastok  路  18Comments

heumn picture heumn  路  27Comments

ishabazz picture ishabazz  路  24Comments

rnystrom picture rnystrom  路  34Comments