IGListKit/Source/IGListCollectionContext.h
Ryan Nystrom 623ff2a8a8 Container size doesnt use content inset, add new APIs
Summary:
The content inset of a collection view can change at any time (as it does with our refresh control) and isn't a good measure of the container size. I don't want to totally remove that API though, so I changed the default behavior, added an insets API, and also added the functionality of the original in a new API.

This makes sizes much more deterministic.

Reviewed By: jessesquires

Differential Revision: D4800758

fbshipit-source-id: 85ce843b5b1c297cea2e2ea705fa255617cbe356
2017-03-30 09:35:03 -07:00

269 lines
12 KiB
Objective-C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 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 <UIKit/UIKit.h>
#import <IGListKit/IGListBatchContext.h>
NS_ASSUME_NONNULL_BEGIN
@class IGListSectionController;
@protocol IGListSectionType;
/**
The collection context provides limited access to the collection-related information that
section controllers need for operations like sizing, dequeing cells, insterting, deleting, reloading, etc.
*/
@protocol IGListCollectionContext <NSObject>
/**
The size of the collection view. You can use this for sizing cells.
*/
@property (nonatomic, readonly) CGSize containerSize;
/**
The content insets of the collection view. You can use this for sizing cells.
*/
@property (nonatomic, readonly) UIEdgeInsets containerInset;
/**
The size of the collection view with content insets applied.
*/
@property (nonatomic, readonly) CGSize insetContainerSize;
/**
Returns size of the collection view relative to the section controller.
@param sectionController The section controller requesting this information.
@return The size of the collection view minus the given section controller's insets.
*/
- (CGSize)containerSizeForSectionController:(IGListSectionController<IGListSectionType> *)sectionController;
/**
Returns the index of the specified cell in the collection relative to the section controller.
@param cell An existing cell in the collection.
@param sectionController The section controller requesting this information.
@return The index of the cell or `NSNotFound` if it does not exist in the collection.
*/
- (NSInteger)indexForCell:(UICollectionViewCell *)cell
sectionController:(IGListSectionController<IGListSectionType> *)sectionController;
/**
Returns the cell in the collection at the specified index for the section controller.
@param index The index of the desired cell.
@param sectionController The section controller requesting this information.
@return The collection view cell, or `nil` if not found.
@warning This method may return `nil` if the cell is offscreen.
*/
- (nullable __kindof UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index
sectionController:(IGListSectionController<IGListSectionType> *)sectionController;
/**
Returns the visible cells for the given section controller.
@param sectionController The section controller requesting this information.
@return An array of visible cells, or an empty array if none are found.
*/
- (NSArray<UICollectionViewCell *> *)visibleCellsForSectionController:(IGListSectionController<IGListSectionType> *)sectionController;
/**
Returns the visible paths for the given section controller.
@param sectionController The section controller requesting this information.
@return An array of visible index paths, or an empty array if none are found.
*/
- (NSArray<NSIndexPath *> *)visibleIndexPathsForSectionController:(IGListSectionController<IGListSectionType> *) sectionController;
/**
Deselects a cell in the collection.
@param index The index of the item to deselect.
@param sectionController The section controller requesting this information.
@param animated Pass `YES` to animate the change, `NO` otherwise.
*/
- (void)deselectItemAtIndex:(NSInteger)index
sectionController:(IGListSectionController<IGListSectionType> *)sectionController
animated:(BOOL)animated;
/**
Returns the section index of an section controller.
@param sectionController An section controller object.
@return The section index of the controller if found, otherwise `NSNotFound`.
*/
- (NSInteger)sectionForSectionController:(IGListSectionController<IGListSectionType> *)sectionController;
/**
Dequeues a cell from the collection view reuse pool.
@param cellClass The class of the cell you want to dequeue.
@param sectionController The section controller requesting this information.
@param index The index of the cell.
@return A cell dequeued from the reuse pool or a newly created one.
@note This method uses a string representation of the cell class as the identifier.
*/
- (__kindof UICollectionViewCell *)dequeueReusableCellOfClass:(Class)cellClass
forSectionController:(IGListSectionController<IGListSectionType> *)sectionController
atIndex:(NSInteger)index;
/**
Dequeues a cell from the collection view reuse pool.
@param nibName The name of the nib file.
@param bundle The bundle in which to search for the nib file. If `nil`, this method searches the main bundle.
@param sectionController The section controller requesting this information.
@param index The index of the cell.
@return A cell dequeued from the reuse pool or a newly created one.
@note This method uses a string representation of the cell class as the identifier.
*/
- (__kindof UICollectionViewCell *)dequeueReusableCellWithNibName:(NSString *)nibName
bundle:(nullable NSBundle *)bundle
forSectionController:(IGListSectionController<IGListSectionType> *)sectionController
atIndex:(NSInteger)index;
/**
Dequeues a storyboard prototype cell from the collection view reuse pool.
@param identifier The identifier of the cell prototype in storyboard.
@param sectionController The section controller requesting this information.
@param index The index of the cell.
@return A cell dequeued from the reuse pool or a newly created one.
*/
- (__kindof UICollectionViewCell *)dequeueReusableCellFromStoryboardWithIdentifier:(NSString *)identifier
forSectionController:(IGListSectionController <IGListSectionType> *)sectionController
atIndex:(NSInteger)index;
/**
Dequeues a supplementary view from the collection view reuse pool.
@param elementKind The kind of supplementary veiw.
@param sectionController The section controller requesting this information.
@param viewClass The class of the supplementary view.
@param index The index of the supplementary vew.
@return A supplementary view dequeued from the reuse pool or a newly created one.
@note This method uses a string representation of the view class as the identifier.
*/
- (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)elementKind
forSectionController:(IGListSectionController<IGListSectionType> *)sectionController
class:(Class)viewClass
atIndex:(NSInteger)index;
/**
Dequeues a supplementary view from the collection view reuse pool.
@param elementKind The kind of supplementary veiw.
@param identifier The identifier of the supplementary view in storyboard.
@param sectionController The section controller requesting this information.
@param index The index of the supplementary vew.
@return A supplementary view dequeued from the reuse pool or a newly created one.
*/
- (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewFromStoryboardOfKind:(NSString *)elementKind
withIdentifier:(NSString *)identifier
forSectionController:(IGListSectionController<IGListSectionType> *)sectionController
atIndex:(NSInteger)index;
/**
Dequeues a supplementary view from the collection view reuse pool.
@param elementKind The kind of supplementary veiw.
@param sectionController The section controller requesting this information.
@param nibName The name of the nib file.
@param bundle The bundle in which to search for the nib file. If `nil`, this method searches the main bundle.
@param index The index of the supplementary vew.
@return A supplementary view dequeued from the reuse pool or a newly created one.
@note This method uses a string representation of the view class as the identifier.
*/
- (__kindof UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:(NSString *)elementKind
forSectionController:(IGListSectionController<IGListSectionType> *)sectionController
nibName:(NSString *)nibName
bundle:(nullable NSBundle *)bundle
atIndex:(NSInteger)index;
/**
Invalidate the backing `UICollectionViewLayout` for all items in the section controller.
@param sectionController The section controller that needs invalidating.
@param completion An optional completion block to execute when the updates are finished.
@note This method can be wrapped in `UIView` animation APIs to control the duration or perform without animations. This
will end up calling `-[UICollectionView performBatchUpdates:completion:] internally, so invalidated changes may not be
reflected in the cells immediately.
*/
- (void)invalidateLayoutForSectionController:(IGListSectionController<IGListSectionType> *)sectionController
completion:(nullable void (^)(BOOL finished))completion;
/**
Batches and performs many cell-level updates in a single transaction.
@param animated A flag indicating if the transition should be animated.
@param updates A block with a context parameter to make mutations.
@param completion An optional completion block to execute when the updates are finished.
@note You should make state changes that impact the number of items in your section controller within the updates
block alongside changes on the context object.
For example, inside your section controllers, you may want to delete *and* insert into the data source that backs your
section controller. For example:
```
[self.collectionContext performBatchItemUpdates:^ (id<IGListBatchContext> batchContext>){
// perform data source changes inside the update block
[self.items addObject:newItem];
[self.items removeObjectAtIndex:0];
NSIndexSet *inserts = [NSIndexSet indexSetWithIndex:[self.items count] - 1];
[batchContext insertInSectionController:self atIndexes:inserts];
NSIndexSet *deletes = [NSIndexSet indexSetWithIndex:0];
[batchContext deleteInSectionController:self atIndexes:deletes];
} completion:nil];
```
@warning You **must** perform data modifications **inside** the update block. Updates will not be performed
synchronously, so you should make sure that your data source changes only when necessary.
*/
- (void)performBatchAnimated:(BOOL)animated
updates:(void (^)(id<IGListBatchContext> batchContext))updates
completion:(nullable void (^)(BOOL finished))completion;
/**
Scrolls to the specified section controller in the list.
@param sectionController The section controller.
@param index The index of the item in the section controller to which to scroll.
@param scrollPosition An option that specifies where the item should be positioned when scrolling finishes.
@param animated A flag indicating if the scrolling should be animated.
*/
- (void)scrollToSectionController:(IGListSectionController<IGListSectionType> *)sectionController
atIndex:(NSInteger)index
scrollPosition:(UICollectionViewScrollPosition)scrollPosition
animated:(BOOL)animated;
@end
NS_ASSUME_NONNULL_END