Prevent negative spaces for items and supplementaries

Summary:
If a negative height/width comes down, cap it to `0.0`.

Issue fixed: #566

Also fixes t16455632 internally.

- [x] All tests pass. Demo project builds and runs.
- [x] I added tests, an experiment, or detailed why my change isn't tested.
- [x] I added an entry to the `CHANGELOG.md` for any breaking changes, enhancements, or bug fixes.
Closes https://github.com/Instagram/IGListKit/pull/583

Differential Revision: D4797520

Pulled By: jessesquires

fbshipit-source-id: 3eeec5244a445bb451460286b4f006ca0d9c67d1
This commit is contained in:
Ryan Nystrom
2017-03-29 14:58:43 -07:00
committed by Facebook Github Bot
parent a98c4ff252
commit 4e9b0bb4c4
8 changed files with 54 additions and 15 deletions

View File

@@ -90,6 +90,8 @@ This release closes the [3.0.0 milestone](https://github.com/Instagram/IGListKit
- Fix a potential crash when a section is moved and deleted at the same time. [Ryan Nystrom](https://github.com/rnystrom) [(#577)](https://github.com/Instagram/IGListKit/pull/577)
- Prevent section controllers and supplementary sources from returning negative sizes that crash `UICollectionViewFlowLayout`. [Ryan Nystrom](https://github.com/rnystrom) [(#583)](https://github.com/Instagram/IGListKit/pull/583)
2.1.0
-----

View File

@@ -458,14 +458,16 @@
IGAssertMainThread();
IGListSectionController <IGListSectionType> *sectionController = [self sectionControllerForSection:indexPath.section];
return [sectionController sizeForItemAtIndex:indexPath.item];
const CGSize size = [sectionController sizeForItemAtIndex:indexPath.item];
return CGSizeMake(MAX(size.width, 0.0), MAX(size.height, 0.0));
}
- (CGSize)sizeForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath {
IGAssertMainThread();
id <IGListSupplementaryViewSource> supplementaryViewSource = [self supplementaryViewSourceAtIndexPath:indexPath];
if ([[supplementaryViewSource supportedElementKinds] containsObject:elementKind]) {
return [supplementaryViewSource sizeForSupplementaryViewOfKind:elementKind atIndex:indexPath.item];
const CGSize size = [supplementaryViewSource sizeForSupplementaryViewOfKind:elementKind atIndex:indexPath.item];
return CGSizeMake(MAX(size.width, 0.0), MAX(size.height, 0.0));
}
return CGSizeZero;
}

View File

@@ -1083,4 +1083,32 @@ XCTAssertEqual(CGSizeEqualToSize(size, s), YES); \
IGAssertEqualSize([self.adapter containerSizeForSectionController:controller], 98, 98);
}
- (void)test_whenSectionControllerReturnsNegativeSize_thatAdapterReturnsZero {
self.dataSource.objects = @[@1];
IGListTestSection *section = [self.adapter sectionControllerForObject:self.dataSource.objects[0]];
section.size = CGSizeMake(-1, -1);
const CGSize size = [self.adapter sizeForItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
XCTAssertEqual(size.width, 0.0);
XCTAssertEqual(size.height, 0.0);
}
- (void)test_whenSupplementarySourceReturnsNegativeSize_thatAdapterReturnsZero {
self.dataSource.objects = @[@1];
[self.adapter reloadDataWithCompletion:nil];
IGTestSupplementarySource *supplementarySource = [IGTestSupplementarySource new];
supplementarySource.collectionContext = self.adapter;
supplementarySource.supportedElementKinds = @[UICollectionElementKindSectionFooter];
supplementarySource.size = CGSizeMake(-1, -1);
IGListSectionController<IGListSectionType> *controller = [self.adapter sectionControllerForObject:@1];
controller.supplementaryViewSource = supplementarySource;
supplementarySource.sectionController = controller;
const CGSize size = [self.adapter sizeForSupplementaryViewOfKind:UICollectionElementKindSectionHeader
atIndexPath:[NSIndexPath indexPathForItem:0 inSection:0]];
XCTAssertEqual(size.width, 0.0);
XCTAssertEqual(size.height, 0.0);
}
@end

View File

@@ -16,6 +16,8 @@
@property (nonatomic, assign) NSInteger items;
@property (nonatomic, assign) CGSize size;
@property (nonatomic, assign) BOOL wasSelected;
@end

View File

@@ -11,6 +11,13 @@
@implementation IGListTestSection
- (instancetype)init {
if (self = [super init]) {
_size = CGSizeMake(100, 10);
}
return self;
}
- (NSArray <Class> *)cellClasses {
return @[UICollectionViewCell.class];
}
@@ -20,7 +27,7 @@
}
- (CGSize)sizeForItemAtIndex:(NSInteger)index {
return CGSizeMake(100, 10);
return self.size;
}
- (UICollectionViewCell *)cellForItemAtIndex:(NSInteger)index {

View File

@@ -26,10 +26,4 @@
return CGSizeMake([self.collectionContext containerSize].width, 45);
}
- (CGSize)estimatedSizeForSupplementaryViewOfKind:(NSString *)elementKind
atIndex:(NSInteger)index {
return CGSizeZero;
}
@end

View File

@@ -15,6 +15,8 @@
@property (nonatomic, assign) BOOL dequeueFromNib;
@property (nonatomic, assign) CGSize size;
@property (nonatomic, strong, readwrite) NSArray<NSString *> *supportedElementKinds;
@property (nonatomic, weak) id<IGListCollectionContext> collectionContext;

View File

@@ -13,6 +13,13 @@
@implementation IGTestSupplementarySource
- (instancetype)init {
if (self = [super init]) {
_size = CGSizeMake(100, 10);
}
return self;
}
#pragma mark - IGListSupplementaryViewSource
- (UICollectionReusableView *)viewForSupplementaryElementOfKind:(NSString *)elementKind
@@ -34,12 +41,7 @@
}
- (CGSize)sizeForSupplementaryViewOfKind:(NSString *)elementKind atIndex:(NSInteger)index {
return CGSizeMake([self.collectionContext containerSize].width, 10);
}
- (CGSize)estimatedSizeForSupplementaryViewOfKind:(NSString *)elementKind
atIndex:(NSInteger)index {
return CGSizeZero;
return self.size;
}
@end