Iglistkit: Profile View Controller

Created on 25 Dec 2017  路  7Comments  路  Source: Instagram/IGListKit

I have a very similar model to IG's Profile View Controller with segmented controls returning a new list of objects (with the same top half information: e.g., "followers", "following", bio, etc.). Would a Binding Controller be the wrong way to approach this?

question

All 7 comments

Hey @jboo1212! Sorry for the late response.

On Instagram, we use many different types of section controllers in the profile. The "header" information is divided into section controllers like:

  • Bio info (avatar, follower counts, etc)
  • Toggle buttons
  • "Other" accounts

Then we have a separate section controller for _each_ grid item.

We don't use binding section controllers in profile mostly b/c each of these section controllers has only a few, usually static cells.

If you have sections of data that are highly dynamic, I'd recommend using binding. However for grid items, I'd encourage you to stick to a single section controller per item (returning just 1 cell). That makes your view controller simpler, and encapsulates all of the business logic for each grid item.

Let me know if that makes sense!

You mean a section controller like...
https://github.com/Instagram/IGListKit/tree/master/Examples/Examples-iOS/IGListKitExamples/ViewControllers

Where the section controller takes in some array of a type and 1 Section Controller is returned with 1 cell or 1 Section Controller for N cells like below...

https://github.com/Instagram/IGListKit/blob/master/Examples/Examples-iOS/IGListKitExamples/SectionControllers/GridSectionController.swift

Maybe I'm just thinking 1 section controller with 1 cell is less efficient and I'm stuck in that mentality?

Still not quite getting it =/...

What Ryan means that use different section controllers for different parts of the screen. For example, if you have a store. You could have different sections for example to show opening hours block, or the location of the store. I am having an array of models which need to be rendered, I do this by splitting up an Store model in value objects so it's easier to use with IGListKit. Below is a code snippet, this reuses a bunch of section controller.

You could end up with something like this:

    func listAdapter(_ listAdapter: ListAdapter, sectionControllerFor object: Any) -> ListSectionController {
        switch object {
        case is String: return SectionTitleSectionController()
        case is StoreFieldModel: return FieldSectionController()
        case is StoreOpeningHourModel: return OpeningTimeSectionController()
        case is StoreLocationModel: return LocationSectionController()
        case is StoreServiceModel: return ServiceSectionController()
        default: fatalError("Unhandled object: \(object)")
        }
    }

The OpeningTimeSectionController would then use the viewModelsFor-method to return a list of value objects which will be rendered as in this case I need to do parsing and sorting. E.g. group all the days with the sam opening hours so you get Mo - Wed 09:00-17:30 and move the days the store is closed to the bottom.

Now I could just reuse my OpeningTimeSectionController by mix and matching it on other screens where I might want to display the opening hours. E.g. product available at store.

@jboo1212 Does this make sense?

Hi Weyert,

Sorry I was unclear earlier about what I didn't understand! My bad. What I meant was if I just have a Comment object and nothing else that should be returned in the section controller, is it better to feed this into a wrapper array with the number of cells being returned as the number of items or to just return a section controller for each Comment...

class LiveChatComment: ListDiffable {

let profilePic: UIImage
let comment: String
let time = Date()

init(profilePic: UIImage, comment: String) {
    self.profilePic = profilePic
    self.comment = comment
}

func diffIdentifier() -> NSObjectProtocol {
    return self.comment + self.time.description + self.profilePic.description as NSObjectProtocol
}

func isEqual(toDiffableObject object: ListDiffable?) -> Bool {
    guard self !== object else { return true }
    guard let object = object as? LiveChatComment else { return false }
    return self.profilePic == object.profilePic && self.comment == object.comment
}

E.g. like Ryan's Binding Model example regarding a Post object but the objects are a list of Comments and not a Post containing a list of Comments.

I鈥檇 try to think about the design of your system:

  • Are all the comments part of a group where they share some business logic? Then they should probably be in the same S.C.

    • For Instagrams posts, app the comments belong to the same post, so they are attached to a top level model and live in the same S.C.

  • Are the comments displayed independent of each other? If so, then they should each have their own S.C.

That should help drive your architecture.

Sent with GitHawk

Gotcha. It would be the second option then. Thanks so much @rnystrom | @weyert !

Was this page helpful?
0 / 5 - 0 ratings

Related issues

iwasrobbed picture iwasrobbed  路  3Comments

rnystrom picture rnystrom  路  3Comments

joseph-francis picture joseph-francis  路  3Comments

racer1988 picture racer1988  路  3Comments

krysztalzg picture krysztalzg  路  3Comments