README and documentationIGListKit version: 3.0.0Hi guys! Basically I'm stuck with one crash and I'm not getting why.
Model
import Foundation
import IGListKit
class CategoryDetailsSection: NSObject {
var images: [Image]
var offSet: OffSet
init(withImages images: [Image], offSet: OffSet) {
self.images = images
self.offSet = offSet
super.init()
}
}
// MARK: - ListDiffable
extension CategoryDetailsSection: ListDiffable {
func diffIdentifier() -> NSObjectProtocol {
return self
}
func isEqual(toDiffableObject object: ListDiffable?) -> Bool {
return isEqual(object)
}
}
In ViewController I have the an endpoint response that I need to display
func displayGetCategoryDetailsSuccess(viewModel: CategoryDetailsModel.GetCategoryDetails.ViewModel) {
activityView.stopAnimating()
guard case .success(let categoryDetailsSection) = viewModel.resultData else { return }
self.categoryDetailsSection.offSet = categoryDetailsSection.offSet
self.categoryDetailsSection.images.append(contentsOf: categoryDetailsSection.images)
adapter.performUpdates(animated: true, completion: nil)
}
ListAdapterDataSource is:
extension CategoryDetailsViewController: ListAdapterDataSource {
func objects(for listAdapter: ListAdapter) -> [ListDiffable] {
return [categoryDetailsSection]
}
func listAdapter(_ listAdapter: ListAdapter, sectionControllerFor object: Any) -> ListSectionController {
return CategoryDetailsSectionController()
}
func emptyView(for listAdapter: ListAdapter) -> UIView? { return nil }
}
categoryDetailsSection is an CategoryDetailsSection object which was init in this way:
fileprivate var categoryDetailsSection = CategoryDetailsSection(withImages: [Image](),
offSet: OffSet(inPage: 0, maxPerPage: 0))
SectionController is:
class CategoryDetailsSectionController: ListSectionController {
// MARK: - Logic Properties
fileprivate var categoryDetailsSection: CategoryDetailsSection!
override func numberOfItems() -> Int {
return categoryDetailsSection.images.count
}
override func sizeForItem(at index: Int) -> CGSize {
return CGSize(width: collectionContext!.containerSize.width - 50.0, height: collectionContext!.containerSize.width - 50.0)
}
override func cellForItem(at index: Int) -> UICollectionViewCell {
let cell = collectionContext?.dequeueReusableCell(of: CategoryDetailsSectionCell.self, for: self, at: index) as! CategoryDetailsSectionCell
cell.loadUIObjects(withImage: categoryDetailsSection.images[index])
return cell
}
override func didUpdate(to object: Any) {
categoryDetailsSection = object as? CategoryDetailsSection
}
override func didSelectItem(at index: Int) {
}
}
So, in ViewController viewDidLoad() is where the endpoint is called and, after I got the response and I parse it, the func displayGetCategoryDetailsSuccess(viewModel: CategoryDetailsModel.GetCategoryDetails.ViewModel) method is called and...CRASH :)
2017-05-28 13:39:25.332231+0200 UpToU[2029:690351] *** Assertion failure in -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3600.8.1/UICollectionView.m:5781
2017-05-28 13:39:25.332941+0200 UpToU[2029:690351] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of items in section 0. The number of items contained in an existing section after the update (10) must be equal to the number of items contained in that section before the update (0), plus or minus the number of items inserted or deleted from that section (0 inserted, 0 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out).'
*** First throw call stack:
(0x18be52fe0 0x18a8b4538 0x18be52eb4 0x18c8ea720 0x19288ec38 0x19289270c 0x1928929ec 0x19289284c 0x1928927d0 0x19215a48c 0x100d9e820 0x100da1424 0x18ad0a9e0 0x18ad0a9a0 0x18ad0f5e8 0x18be010c8 0x18bdfece4 0x18bd2eda4 0x18d798074 0x191fe9058 0x100037194 0x18ad3d59c)
libc++abi.dylib: terminating with uncaught exception of type NSException
Signal: SIGABRT (signal SIGABRT)
Any clue why? If I'm implementing it wrong, how can I add images and display them?
FYI
The reason I'm doing it is because when user reach the bottom of the ScrollView I need to fetch new elements and show them. So I need to append new elements, in this case images, in the previous SectionController.
I'm trying this and seems working but, it is the correct way?
func displayGetCategoryDetailsSuccess(viewModel: CategoryDetailsModel.GetCategoryDetails.ViewModel) {
activityView.stopAnimating()
guard case .success(let categoryDetailsSection) = viewModel.resultData else { return }
guard let sectionController = adapter.sectionController(forSection: 0) as? CategoryDetailsSectionController else { return }
sectionController.collectionContext?.performBatch(animated: true,
updates: { batchContext in
let previousCount = sectionController.categoryDetailsSection.images.count
let startIndex = previousCount == 0 ? 0 : previousCount
let endIndex = previousCount + categoryDetailsSection.images.count - 1
sectionController.categoryDetailsSection.offSet = categoryDetailsSection.offSet
sectionController.categoryDetailsSection.images.append(contentsOf: categoryDetailsSection.images)
batchContext.insert(in: sectionController, at: IndexSet(startIndex...endIndex))
},
completion: { completed in
self.categoryDetailsSection = sectionController.categoryDetailsSection
}
)
}
@cikpis it looks like your model has
var images: [Image]
And there is only a single object+section controller in your setup. If you mutate the part of your model that powers numberOfItems() without calling any updates, UICollectionView will throw. I'd recommend:
let)Take a look at how we dynamically update a list as you scroll to the bottom in this example.
Hope that helps!
Hi @rnystrom, thanks for reaching out. The solution you gave me I don't think is the correct one because I don't want to create a section for each elements. I've already saw your example and unfortunately that is not what I was looking for.
I would like to know if there is a proper way to update the same section adding or removing objects, in my case images from CategoryDetailsSection. I succeed in it doing the follow code and my question is if it's the correct way to perform an update of items that power numberOfItems()
guard case .success(let categoryDetailsSection) = viewModel.resultData else { return }
guard let sectionController = adapter.sectionController(forSection: 0) as? CategoryDetailsSectionController else { return }
sectionController.collectionContext?.performBatch(animated: true,
updates: { batchContext in
let previousCount = sectionController.categoryDetailsSection.images.count
let startIndex = previousCount
let endIndex = previousCount + categoryDetailsSection.images.count - 1
sectionController.categoryDetailsSection.offSet = categoryDetailsSection.offSet
sectionController.categoryDetailsSection.images.append(contentsOf: categoryDetailsSection.images)
batchContext.insert(in: sectionController, at: IndexSet(startIndex...endIndex))
},
completion: { completed in
self.categoryDetailsSection = sectionController.categoryDetailsSection
}
)
@cikpis ya, you'll have to manually insert/delete items like you're doing, but that's going to get tedious and is prone for error. You might want to look at using IGListBindingSectionController which will diff+update within the section itself for you, all you have to do is call an update method and things will "just work".
@rnystrom thanks! Even though seems there is no example or guide of how to use it :)
Also I don't know if to be afraid of your "just work" xD
Anyway, do you mind to redirect me in the correct guide or example for IGListBindingSectionController? I haven found nothing about that, thanks in advance!
@cikpis most definitely, we're working on a more in-depth guide now, but for the time being check out the calendar example:
@rnystrom sounds good. Alright then, keep me posted when a guide will be done. Would be nice to have an example with a UICollectionView like in LoadMoreViewController.swift but instead of add section, add elements to the section controller array model.
Hi @rnystrom! Any update about IGListBindingSectionController guide?
@cikpis still hoping to set aside more time for it among a bunch of other priorities atm. I've explored a lot of uses for this SC in Instagram and another sample app, so several learnings and best practices. Will get this prioritized higher.
@rnystrom I am still trying to wrap my head around the SectionController 馃槩, my requirements is somewhat similar to @cikpis 's. All I need to have is a single section with a Supplementary view and cells be added to the same section instead of creating new sections for every cell. There doesn't seem to be anything like numberOfSections that exists and so far my collectionview is creating number of sections = number of cells, which is not what I want. Maybe there is a way to achieve what I am looking for but I can't seem to figure this out using any of the examples. Also, there isn't any example using IGListBindingSectionController, so perhaps it would be helpful to include one.
@annjawn there is an example using the binding control, look for the "calendar" example. It doesn't have dynamically adding content, but its the same. I'll whip up an example of adding content.
Regarding needing a single section controller w/ multiple cells, can you explain why that's a limitation of yours? IGListKit is designed to abstract the idea of cells and sections away from you, instead just focus on your data, cell appearance, and what happens when interacting with a _single_ cell.
Any update on this? Should we close?
@rnystrom still waiting the guideline for binding controller :)
Any update on this @cikpis ? An alternative is always to paper sketch a simple version of what you want to archieve... Maybe I can throw something quick together. The example projects are pretty comprehensive now and I can not really get what you want to archieve that can not be replicated by combining snippets and designs from those.
@heumn when I wrote "still waiting the guideline for binding controller" the guide was still not created and as I said in the other post, I'm not full operative ( still in vacation ) for that I didn't have the time to close this.
Regarding needing a single section controller w/ multiple cells, can you explain why that's a limitation of yours? IGListKit is designed to abstract the idea of cells and sections away from you, instead just focus on your data, cell appearance, and what happens when interacting with a _single_ cell.
I'm using multiple cells in one section since we need the sticky section header.
Most helpful comment
@rnystrom sounds good. Alright then, keep me posted when a guide will be done. Would be nice to have an example with a UICollectionView like in
LoadMoreViewController.swiftbut instead of add section, add elements to the section controller array model.