Instagram / IGListKit

A data-driven UICollectionView framework for building fast and flexible lists.
https://instagram.github.io/IGListKit/
MIT License
12.85k stars 1.54k forks source link

Different sectionController upon update #389

Closed Sherlouk closed 7 years ago

Sherlouk commented 7 years ago

Working on a little bit of a project but hit an issue that I wasn't quite sure on the functionality behind.

I'm trying to achieve a list with two different sectionControllers. For the sake of complexity we'll call them "Big" and "Small".

Every object has an itemType, if this is "a" then I want it to use the "Big" controller, and if it's "b" then to use the "Small" controller. Equally, and for me more of an issue (as itemType is unlikely to change) I always want the first item in a list to use the "Big" controller.

(I'm no Jony Ive but hope this makes it a bit clearer what I'm talking about: http://prntscr.com/dsc4mb)

The issue that I'm having though is if I move the object that was at the top of the list, and it gets moved down then it stays as the "Big" controller. And the new item at the top is "Small".

For what it's worth, to identify somehting as "first in a list" I am in the listAdapter(sectionControllerFor object) checking for the index of object in the objects(for listAdapter) response. To trigger the update I am simply using performUpdates(animated: true).

--

Is it possible to achieve the functionality I want through different sectionControllers? SectionController's have isFirstSection so I wouldn't need to do my calculation -- would it be better to swap the cell rather the sectionController?

Thanks in advance!

rnystrom commented 7 years ago

@Sherlouk is the functionality and behavior exactly the same between the first object and the rest? Do they use the same cell just different sizes? The mockup makes it look like there is more content on the smaller cells than the banner.

One way to make the item reload if it is moved is by using this itemType in the model's -isEqualToDiffableObject: method. If the type was "a", but then its not the first so its now "b", then the equality check should fail and the section will be reloaded.

Sherlouk commented 7 years ago

Both "a" and "b" present the same information just in a slightly different style

I've updated the equality check for the itemType, didn't think of that -- great idea! However, that still doesn't help with the index change as the object doesn't know where it's going to be shown?

rnystrom commented 7 years ago

@Sherlouk I'd recommend that the section controller try not to know about its position. Instead, when building the array of objects in your data source, do something like:

var objects = [IGListDiffable]()

for model in models {
  let type = model === models.first ? "a" : "b"
  objects.append(SectionModel(itemType: type))
}

return objects
Sherlouk commented 7 years ago

@rnystrom Correct me if I'm wrong, so add a new property to my model which is essentially "cellType" and set that in my data source -- then add that to the equality check as well so if it changes then update the controller?

rnystrom commented 7 years ago

@Sherlouk doesn't itemType or w/e already exist? But basically ya:

Sherlouk commented 7 years ago

The issue with overriding itemType is that's not always a representative of the cell type.

So if I have item types such as "story", "video", "live" - I then don't want to treat the first item as a "video" in order to trick it into making it large. I need the flexibility to have a large story for example.

Think I can make that work though, thanks for the suggestion!

jessesquires commented 7 years ago

@Sherlouk - You should map your data models to view models.

Sherlouk commented 7 years ago

@jessesquires - In the end I made a point of redoing a whole bunch of my models, got to the point where the structure made sense at the start, but now was beginning to be a hindrance.

So yeah I do now have view models, and some other niceties - taking advantage of IGListKits abilities!

rnystrom commented 7 years ago

Once #38 is finished (eta tbd) it'll make map(model) -> [viewModels] then map(viewModels) -> cell.configure(viewModel) at lot more explicit and automated (at least that's what I hope 😅)

Sherlouk commented 7 years ago

@rnystrom Would love to help with all that but my Obj-C doesn't extend beyond adding a few #import statements 😅

Did get it working in the end though, now just trying to deal with dynamic heights 🤔