Iglistkit: Design choice and a heavy load advice

Created on 22 Dec 2016  Â·  11Comments  Â·  Source: Instagram/IGListKit

Sorry for the clickbait in title. :-)
I'm faced with massive VC and this IGListKit project is a kind of an answer to my prayers. Thanks.

A question about a good design choice with IGListKit follows.

Problem

I have a list that can grow to a couple of thousands (most likely couple of hundreds), with very dispersed cell types (like 10-ish different cell types). I know it can be dynamically loaded, in pages, but let's stick for the sake of the conversation with a huge cell numbers...

The easiest way to imagine it is as if you have a classic messenger-type list, like Viber or WhatsApp (collection view) with a lot of messages (textual, images, movies, games, location stuff...) in the conversation. These messages are not grouped, there virtually can be no consecutive two cells of the same type.

Current solution

In my test project I have approached to this problem with section controllers with just one item (numberOfItems always returns 1). This means that a number of IGListSectionControllers is equal to the number of "messages" in this collection view.

Question

Does it make a sense? What would be (if any) a better approach? Are there any restrictions on having _a lot_ of section controllers with a relatively small number of items inside (one)?
I don't see any problems with it, IGListSectionControllers is not massive, but still would like to confirm it with the makers.

New issue checklist

General information

  • IGListKit version: HEAD
  • iOS version(s): 9,10
  • CocoaPods/Carthage version: latest
  • Xcode version: 8.2.1
  • Devices/Simulators affected:
  • Reproducible in the demo project? (Yes/No):
  • Related issues:
question

Most helpful comment

This is exactly how we model IG Direct (messages). Section controllers have 1 item and produce 1 cell — and there are around a dozen different message types.

Architecture is:

Message Model -> View Model -> Section Controller -> Cell

Each model gets mapped to a view model. The view model is given to the section controller. The cell configures itself with the view model.

All 11 comments

@iostriz all questions welcome! And this is a great one.

Generally I'd recommend modeling a section controller per model. Whether you break that model down into an array of view models, or, like you described, just return 1 item, is totally up to you.

Within Instagram we do a mix of both strategies. When we display feed items we can have a _lot_ of them loaded at once (imagine scrolling through Instagram for a long time...) with tons of different cell types. We use a single section controller and an array of view models to represent each cell.

We group models into logical bundles for things like chat UIs, and we also have UIs where there's a single cell and model per section controller.

I would try to reason about what the barrier is between your models, cells, and business logic. If some cells are all powered by the same model or interact with each other in some way, I'd use a single section controller. However if they are all totally independent I'd say go for 1 item per.

I _love_ jamming on this architecture stuff, so feel free to throw more ideas/questions at me!

This is exactly how we model IG Direct (messages). Section controllers have 1 item and produce 1 cell — and there are around a dozen different message types.

Architecture is:

Message Model -> View Model -> Section Controller -> Cell

Each model gets mapped to a view model. The view model is given to the section controller. The cell configures itself with the view model.

@rnystrom @jessesquires

I have a little similar architectural problem i want to create messaging app. Messages would be grouped by date they were sent (in uitableview i would handle it with grouping messages sent during a certain day into sections and add sticky headers for every day). Also of course i will have multiple kinds of messages types etc.

So as I understand you'd suggest 1 section controller per message. But then how do you group it ?
is it good practice to model it like this ?

 func objects(for listAdapter: IGListAdapter) -> [IGListDiffable] {
        return [Message(),DateHeader(),Message(), Message()] as! [IGListDiffable]
    }

Or Rather

 func objects(for listAdapter: IGListAdapter) -> [IGListDiffable] {
        return [Message(),Message(), Message()] as! [IGListDiffable]
    }

and just decorate Message object with a flag that its the first one of new day and should display supplementaryView on that one?

Or any other idea what would be best practice to solve this ? I feel strange to not have my messages somehow grouped with a section array. At the same time i think a section per day with multiple messages could be too big thing ?

I had the very same solution for grouping in dates. But, after some struggling, I have decided to abandon that solution in the favour of the dumbest one - I just insert one special cell of type "date separator" wherever appropriate. That way I have very simple collection view, and a little bit more of the housekeeping model data. Seems that it does not tend to break in "performBatchUpdates" :-).

@ammoqq What I would actually recommend is creating a model that represents a section of data instead.

class MessageSection: IGListDiffable {
  let messages: [Message]
  let fromDate: Date
  let toDate: Date

  func diffIdentifier() -> NSObjectProtocol {
    // something to uniquely id the date range
    return fromDate.description + toDate.description
  }

  func isEqual(toDiffableObject object: IGListDiffable) -> Bool {
    if self === object { return true }
    guard let object = object as? MessageSection else { return false }
    return messages == object.messages
  }
}

Then create a section controller that receives this model and uses the messages or w/e array to power numberOfItems. I do exactly this in a hobby weather app I'm making:

I would be really liberal with making models, transforming them as they pass down through different systems, all the way to the cell.

@iostriz fyi I edited what I hope was a typo 😉

@rnystrom Haha, yeah, sure, was a typo... Thanks! I adore it too much sometimes.

@rnystrom glad to have run across your explanation above. Running into the same concept with showing events in a list separated by day.

I get the idea of creating a "MessageSection" in this case, but, if I'm understanding this correctly, when a single message is updated there is no easy way to let the adapter know to reload that message. Since the message represents a cell and not a section, the only way to reload it if to reload the entire "MessageSection." Thus you lose the individual animations and such?

@zachwhelchel sadly, yup you can't get a "uni directional" data flow and cell (item) level animations... yet. #494 will make that possible.

In Instagram we have mutable models that respond to changes by inserting/deleting/updating cells. While this works, #494 is where we want to be so data can flow in from the top and not have to do any side-stepping.

@rnystrom uhm, what can I do if every messageCell is composed of multiple cells?
MessageSectionsController (ListStackedSectionController) -> single SectionController -> messageCell composed of multiple cells.

@asimonv I'd recommend opening a new issue, this one is really old.

@asimonv I'd recommend opening a new issue, this one is really old.

@rnystrom sure!

Sent with GitHawk

Was this page helpful?
0 / 5 - 0 ratings

Related issues

racer1988 picture racer1988  Â·  3Comments

alexwillrock picture alexwillrock  Â·  3Comments

kanumuri9593 picture kanumuri9593  Â·  3Comments

shuhrat10 picture shuhrat10  Â·  3Comments

iwasrobbed picture iwasrobbed  Â·  3Comments