mirror of
https://github.com/Instagram/IGListKit
synced 2026-05-15 05:18:18 +00:00
Summary: This was a little bit of an invasive change with the display handler, but I think that this is the right call. When sending display events for objects, we should account for the supplementary view as part of the section controller. This is especially useful for headers and footers. Note that this wont effect the working range API at all. Fixes #300 Closes https://github.com/Instagram/IGListKit/pull/470 Differential Revision: D4551338 Pulled By: rnystrom fbshipit-source-id: dda6fbf18bcfc2c941d80ee2314a543d1ab83843
125 lines
5.6 KiB
Objective-C
125 lines
5.6 KiB
Objective-C
/**
|
|
* Copyright (c) 2016-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under the BSD-style license found in the
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
*/
|
|
|
|
#import "IGListDisplayHandler.h"
|
|
|
|
#import <IGListKit/IGListAssert.h>
|
|
#import <IGListKit/IGListAdapter.h>
|
|
#import <IGListKit/IGListDisplayDelegate.h>
|
|
#import <IGListKit/IGListSectionController.h>
|
|
|
|
@interface IGListDisplayHandler ()
|
|
|
|
@property (nonatomic, strong) NSCountedSet *visibleListSections;
|
|
@property (nonatomic, strong) NSMapTable *visibleViewObjectMap;
|
|
|
|
@end
|
|
|
|
@implementation IGListDisplayHandler
|
|
|
|
- (instancetype)init {
|
|
if (self = [super init]) {
|
|
_visibleListSections = [[NSCountedSet alloc] init];
|
|
_visibleViewObjectMap = [[NSMapTable alloc] initWithKeyOptions:NSMapTableStrongMemory valueOptions:NSMapTableStrongMemory capacity:0];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (id)pluckObjectForView:(UICollectionReusableView *)view {
|
|
NSMapTable *viewObjectMap = self.visibleViewObjectMap;
|
|
id object = [viewObjectMap objectForKey:view];
|
|
[viewObjectMap removeObjectForKey:view];
|
|
return object;
|
|
}
|
|
|
|
- (void)willDisplayReusableView:(UICollectionReusableView *)view
|
|
forListAdapter:(IGListAdapter *)listAdapter
|
|
sectionController:(IGListSectionController<IGListSectionType> *)sectionController
|
|
object:(id)object
|
|
indexPath:(NSIndexPath *)indexPath {
|
|
IGParameterAssert(view != nil);
|
|
IGParameterAssert(listAdapter != nil);
|
|
IGParameterAssert(object != nil);
|
|
IGParameterAssert(indexPath != nil);
|
|
|
|
[self.visibleViewObjectMap setObject:object forKey:view];
|
|
NSCountedSet *visibleListSections = self.visibleListSections;
|
|
if ([visibleListSections countForObject:sectionController] == 0) {
|
|
[sectionController.displayDelegate listAdapter:listAdapter willDisplaySectionController:sectionController];
|
|
[listAdapter.delegate listAdapter:listAdapter willDisplayObject:object atIndex:indexPath.section];
|
|
}
|
|
[visibleListSections addObject:sectionController];
|
|
}
|
|
|
|
- (void)didEndDisplayingReusableView:(UICollectionReusableView *)view
|
|
forListAdapter:(IGListAdapter *)listAdapter
|
|
sectionController:(IGListSectionController<IGListSectionType> *)sectionController
|
|
object:(id)object
|
|
indexPath:(NSIndexPath *)indexPath {
|
|
IGParameterAssert(view != nil);
|
|
IGParameterAssert(listAdapter != nil);
|
|
IGParameterAssert(indexPath != nil);
|
|
|
|
if (object == nil || sectionController == nil) {
|
|
return;
|
|
}
|
|
|
|
const NSInteger section = indexPath.section;
|
|
|
|
NSCountedSet *visibleSections = self.visibleListSections;
|
|
[visibleSections removeObject:sectionController];
|
|
|
|
if ([visibleSections countForObject:sectionController] == 0) {
|
|
[sectionController.displayDelegate listAdapter:listAdapter didEndDisplayingSectionController:sectionController];
|
|
[listAdapter.delegate listAdapter:listAdapter didEndDisplayingObject:object atIndex:section];
|
|
}
|
|
}
|
|
|
|
- (void)willDisplaySupplementaryView:(UICollectionReusableView *)view
|
|
forListAdapter:(IGListAdapter *)listAdapter
|
|
sectionController:(IGListSectionController<IGListSectionType> *)sectionController
|
|
object:(id)object
|
|
indexPath:(NSIndexPath *)indexPath {
|
|
[self willDisplayReusableView:view forListAdapter:listAdapter sectionController:sectionController object:object indexPath:indexPath];
|
|
}
|
|
|
|
- (void)didEndDisplayingSupplementaryView:(UICollectionReusableView *)view
|
|
forListAdapter:(IGListAdapter *)listAdapter
|
|
sectionController:(IGListSectionController<IGListSectionType> *)sectionController
|
|
indexPath:(NSIndexPath *)indexPath {
|
|
// if cell display events break, don't send display events when the object has disappeared
|
|
id object = [self pluckObjectForView:view];
|
|
[self didEndDisplayingReusableView:view forListAdapter:listAdapter sectionController:sectionController object:object indexPath:indexPath];
|
|
}
|
|
|
|
- (void)willDisplayCell:(UICollectionViewCell *)cell
|
|
forListAdapter:(IGListAdapter *)listAdapter
|
|
sectionController:(IGListSectionController<IGListSectionType> *)sectionController
|
|
object:(id)object
|
|
indexPath:(NSIndexPath *)indexPath {
|
|
id <IGListDisplayDelegate> displayDelegate = [sectionController displayDelegate];
|
|
[displayDelegate listAdapter:listAdapter willDisplaySectionController:sectionController cell:cell atIndex:indexPath.item];
|
|
[self willDisplayReusableView:cell forListAdapter:listAdapter sectionController:sectionController object:object indexPath:indexPath];
|
|
}
|
|
|
|
- (void)didEndDisplayingCell:(UICollectionViewCell *)cell
|
|
forListAdapter:(IGListAdapter *)listAdapter
|
|
sectionController:(IGListSectionController<IGListSectionType> *)sectionController
|
|
indexPath:(NSIndexPath *)indexPath {
|
|
// if cell display events break, don't send cell events to the displayDelegate when the object has disappeared
|
|
id object = [self pluckObjectForView:cell];
|
|
if (object == nil) {
|
|
return;
|
|
}
|
|
|
|
[sectionController.displayDelegate listAdapter:listAdapter didEndDisplayingSectionController:sectionController cell:cell atIndex:indexPath.item];
|
|
[self didEndDisplayingReusableView:cell forListAdapter:listAdapter sectionController:sectionController object:object indexPath:indexPath];
|
|
}
|
|
|
|
@end
|