2016-09-07 22:37:59 +00:00
|
|
|
/**
|
|
|
|
|
* 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 ()
|
|
|
|
|
|
2017-02-13 14:51:25 +00:00
|
|
|
@property (nonatomic, strong) NSMapTable *visibleViewObjectMap;
|
2016-09-07 22:37:59 +00:00
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation IGListDisplayHandler
|
|
|
|
|
|
|
|
|
|
- (instancetype)init {
|
|
|
|
|
if (self = [super init]) {
|
2017-06-22 16:21:50 +00:00
|
|
|
_visibleListSections = [NSCountedSet new];
|
2017-02-13 14:51:25 +00:00
|
|
|
_visibleViewObjectMap = [[NSMapTable alloc] initWithKeyOptions:NSMapTableStrongMemory valueOptions:NSMapTableStrongMemory capacity:0];
|
2016-09-07 22:37:59 +00:00
|
|
|
}
|
|
|
|
|
return self;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-13 14:51:25 +00:00
|
|
|
- (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
|
2017-04-19 15:17:56 +00:00
|
|
|
sectionController:(IGListSectionController *)sectionController
|
2017-02-13 14:51:25 +00:00
|
|
|
object:(id)object
|
|
|
|
|
indexPath:(NSIndexPath *)indexPath {
|
|
|
|
|
IGParameterAssert(view != nil);
|
2016-09-07 22:37:59 +00:00
|
|
|
IGParameterAssert(listAdapter != nil);
|
|
|
|
|
IGParameterAssert(object != nil);
|
|
|
|
|
IGParameterAssert(indexPath != nil);
|
|
|
|
|
|
2017-02-13 14:51:25 +00:00
|
|
|
[self.visibleViewObjectMap setObject:object forKey:view];
|
|
|
|
|
NSCountedSet *visibleListSections = self.visibleListSections;
|
|
|
|
|
if ([visibleListSections countForObject:sectionController] == 0) {
|
|
|
|
|
[sectionController.displayDelegate listAdapter:listAdapter willDisplaySectionController:sectionController];
|
2016-09-07 22:37:59 +00:00
|
|
|
[listAdapter.delegate listAdapter:listAdapter willDisplayObject:object atIndex:indexPath.section];
|
|
|
|
|
}
|
2017-02-13 14:51:25 +00:00
|
|
|
[visibleListSections addObject:sectionController];
|
2016-09-07 22:37:59 +00:00
|
|
|
}
|
|
|
|
|
|
2017-02-13 14:51:25 +00:00
|
|
|
- (void)didEndDisplayingReusableView:(UICollectionReusableView *)view
|
|
|
|
|
forListAdapter:(IGListAdapter *)listAdapter
|
2017-04-19 15:17:56 +00:00
|
|
|
sectionController:(IGListSectionController *)sectionController
|
2017-02-13 14:51:25 +00:00
|
|
|
object:(id)object
|
|
|
|
|
indexPath:(NSIndexPath *)indexPath {
|
|
|
|
|
IGParameterAssert(view != nil);
|
2016-09-07 22:37:59 +00:00
|
|
|
IGParameterAssert(listAdapter != nil);
|
|
|
|
|
IGParameterAssert(indexPath != nil);
|
|
|
|
|
|
|
|
|
|
if (object == nil || sectionController == nil) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-13 14:51:25 +00:00
|
|
|
const NSInteger section = indexPath.section;
|
2016-09-07 22:37:59 +00:00
|
|
|
|
|
|
|
|
NSCountedSet *visibleSections = self.visibleListSections;
|
|
|
|
|
[visibleSections removeObject:sectionController];
|
2017-02-13 14:51:25 +00:00
|
|
|
|
2016-09-07 22:37:59 +00:00
|
|
|
if ([visibleSections countForObject:sectionController] == 0) {
|
2017-02-13 14:51:25 +00:00
|
|
|
[sectionController.displayDelegate listAdapter:listAdapter didEndDisplayingSectionController:sectionController];
|
2016-09-07 22:37:59 +00:00
|
|
|
[listAdapter.delegate listAdapter:listAdapter didEndDisplayingObject:object atIndex:section];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-13 14:51:25 +00:00
|
|
|
- (void)willDisplaySupplementaryView:(UICollectionReusableView *)view
|
|
|
|
|
forListAdapter:(IGListAdapter *)listAdapter
|
2017-04-19 15:17:56 +00:00
|
|
|
sectionController:(IGListSectionController *)sectionController
|
2017-02-13 14:51:25 +00:00
|
|
|
object:(id)object
|
|
|
|
|
indexPath:(NSIndexPath *)indexPath {
|
|
|
|
|
[self willDisplayReusableView:view forListAdapter:listAdapter sectionController:sectionController object:object indexPath:indexPath];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
- (void)didEndDisplayingSupplementaryView:(UICollectionReusableView *)view
|
|
|
|
|
forListAdapter:(IGListAdapter *)listAdapter
|
2017-04-19 15:17:56 +00:00
|
|
|
sectionController:(IGListSectionController *)sectionController
|
2017-02-13 14:51:25 +00:00
|
|
|
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
|
2017-04-19 15:17:56 +00:00
|
|
|
sectionController:(IGListSectionController *)sectionController
|
2017-02-13 14:51:25 +00:00
|
|
|
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
|
2017-04-19 15:17:56 +00:00
|
|
|
sectionController:(IGListSectionController *)sectionController
|
2017-02-13 14:51:25 +00:00
|
|
|
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];
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-07 22:37:59 +00:00
|
|
|
@end
|