Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

_visibleSectionIndices not being cleaned up in time #1581

Open
2 of 3 tasks
Yasic opened this issue Jun 3, 2023 · 0 comments
Open
2 of 3 tasks

_visibleSectionIndices not being cleaned up in time #1581

Yasic opened this issue Jun 3, 2023 · 0 comments

Comments

@Yasic
Copy link

Yasic commented Jun 3, 2023

New issue checklist

  • I have reviewed the README and documentation
  • I have searched existing issues and this is not a duplicate
  • I have attempted to reproduce the issue and include an example project.

General information

  • IGListKit version: 4.0.0
  • iOS version(s): 16.5
  • CocoaPods/Carthage version: 1.10.1
  • Xcode version: 14.3
  • Devices/Simulators affected: All
  • Reproducible in the demo project? (Yes/No):
  • Related issues:

Debug information

I'm running into a ListWorkingRangeDelegate related issue.

Specifically, my list triggers a load behavior when swiped near the bottom, which loads more elements into the list.My implementation is to judge whether it is the last section in sectionControllerWillEnterWorkingRange of ListWorkingRangeDelegate, and trigger the corresponding loading logic.

Here is the code sample

func listAdapter(_ listAdapter: ListAdapter, sectionControllerWillEnterWorkingRange sectionController: ListSectionController) {
     if sectionController.isLastSection {
         loadMore()
}

If I keep sliding the list, the loading logic will be triggered multiple times, resulting in a lot of list elements, such as hundreds of elements.

At this time, the list may be refreshed for some reasons, such as remote notifications or network requests. The number of elements in the list may change from hundreds to dozens.

At this time, if I slide the list arbitrarily, it will frequently trigger the sectionControllerWillEnterWorkingRange callback of ListWorkingRangeDelegate of the last sectionController, and further trigger the loading logic, which is not in line with expectations.

I read the source code of IGListWorkingRangeHandler and I think I find the answer.

IGListWorkingRangeHandler maintains a collection of _visibleSectionIndices, which stores the indices of the current visible sections.

  • When the willDisplayItemAtIndexPath function is called, IGListWorkingRangeHandler insert the new section into _visibleSectionIndices.
- (void)willDisplayItemAtIndexPath:(NSIndexPath *)indexPath
                     forListAdapter:(IGListAdapter *)listAdapter {
     IGParameterAssert(indexPath != nil);
     IGParameterAssert(listAdapter != nil);

     _visibleSectionIndices.insert({
         .section = indexPath.section,
         .row = indexPath.row,
         .hash = indexPath.hash
     });

     [self _updateWorkingRangesWithListAdapter:listAdapter];
}
  • When didEndDisplayingItemAtIndexPath is called, IGListWorkingRangeHandler clear the displayed section.
- (void)didEndDisplayingItemAtIndexPath:(NSIndexPath *)indexPath
                          forListAdapter:(IGListAdapter *)listAdapter {
     IGParameterAssert(indexPath != nil);
     IGParameterAssert(listAdapter != nil);

     _visibleSectionIndices. erase({
         .section = indexPath.section,
         .row = indexPath.row,
         .hash = indexPath.hash
     });

     [self _updateWorkingRangesWithListAdapter:listAdapter];
}

In the _updateWorkingRangesWithListAdapter method, it will traverse the ListWorkingRangeDelegate methods implemented by the corresponding sectionController according to _visibleSectionIndices.

Back to the problem I encountered, if I slide to the middle of the list in a list with 100 elements, then _visibleSectionIndices is assumed to be [80, 81, 82, 83, 84].

If I refresh the list at this point, the list becomes 50 elements, and the visual elements become [40, 41, 42, 43, 44].

But, at this time, the section of _visibleSectionIndices ([80, 81, 82, 83, 84]) will exceed the number of list elements(50).

Let's see how IGListWorkingRangeHandler handles this boundary case.

image

It can be seen that IGListWorkingRangeHandler cleverly uses the number of objects as the maximum value of end.

Then, although it is still far away from the bottom of the list at this time, the sectionControllerWillEnterWorkingRange method of the last sectionController will be called because of this. So that loading action is started too early before the list reaches the bottom.

The more serious problem is that, the section in _visibleSectionIndices needs to be cleared in the didEndDisplayingItemAtIndexPath method, which will causes sectionControllerWillEnterWorkingRange to be called frequently.

I have temporarily located these information, and did not find that _visibleSectionIndices has any other clearing logic.

I suggest whether _visibleSectionIndices can be cleared when the list is refreshed, or provide an api to clean _visibleSectionIndices.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant