Merge pull request #976 from facebook/CollectionRefactoring

Make ASCollectionView always create an ASCollectionNode.  Add visibility and interfaceState change notifications.
This commit is contained in:
appleguy
2015-12-23 13:09:42 -08:00
13 changed files with 217 additions and 219 deletions

View File

@@ -128,7 +128,7 @@
242995D31B29743C00090100 /* ASBasicImageDownloaderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 242995D21B29743C00090100 /* ASBasicImageDownloaderTests.m */; };
251B8EF71BBB3D690087C538 /* ASCollectionDataController.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF21BBB3D690087C538 /* ASCollectionDataController.h */; };
251B8EF81BBB3D690087C538 /* ASCollectionDataController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 251B8EF31BBB3D690087C538 /* ASCollectionDataController.mm */; };
251B8EF91BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF41BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h */; };
251B8EF91BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF41BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h */; settings = {ATTRIBUTES = (Public, ); }; };
251B8EFA1BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.m in Sources */ = {isa = PBXBuildFile; fileRef = 251B8EF51BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.m */; };
251B8EFB1BBB3D690087C538 /* ASDataController+Subclasses.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF61BBB3D690087C538 /* ASDataController+Subclasses.h */; };
2538B6F31BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2538B6F21BC5D2A2003CA0B4 /* ASCollectionViewFlowLayoutInspectorTests.m */; };
@@ -458,6 +458,7 @@
D785F6621A74327E00291744 /* ASScrollNode.h in Headers */ = {isa = PBXBuildFile; fileRef = D785F6601A74327E00291744 /* ASScrollNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
D785F6631A74327E00291744 /* ASScrollNode.m in Sources */ = {isa = PBXBuildFile; fileRef = D785F6611A74327E00291744 /* ASScrollNode.m */; };
DB7121BCD50849C498C886FB /* libPods-AsyncDisplayKitTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = EFA731F0396842FF8AB635EE /* libPods-AsyncDisplayKitTests.a */; };
DE040EF91C2B40AC004692FF /* ASCollectionViewFlowLayoutInspector.h in Headers */ = {isa = PBXBuildFile; fileRef = 251B8EF41BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.h */; settings = {ATTRIBUTES = (Public, ); }; };
DE6EA3221C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */; };
DE6EA3231C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = DE6EA3211C14000600183B10 /* ASDisplayNode+FrameworkPrivate.h */; };
DECBD6E71BE56E1900CF4905 /* ASButtonNode.h in Headers */ = {isa = PBXBuildFile; fileRef = DECBD6E51BE56E1900CF4905 /* ASButtonNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -1451,6 +1452,7 @@
B35062551B010EFD0018CF92 /* ASSentinel.h in Headers */,
9C8221961BA237B80037F19A /* ASStackBaselinePositionedLayout.h in Headers */,
9C49C3701B853961000B0DD5 /* ASStackLayoutable.h in Headers */,
DE040EF91C2B40AC004692FF /* ASCollectionViewFlowLayoutInspector.h in Headers */,
34EFC7701B701CFA00AD841F /* ASStackLayoutDefines.h in Headers */,
254C6B7B1BF94DF4003EC431 /* ASTextKitRenderer+Positioning.h in Headers */,
CC7FD9E21BB603FF005CCB2B /* ASPhotosFrameworkImageRequest.h in Headers */,
@@ -1523,7 +1525,6 @@
058D09B9195D04C000B7D73C /* Frameworks */,
058D09BA195D04C000B7D73C /* Resources */,
3B9D88CDF51B429C8409E4B6 /* Copy Pods Resources */,
5ADEA7587189397768F2B36C /* Embed Pods Frameworks */,
);
buildRules = (
);
@@ -1623,21 +1624,6 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
1B86F48711505F91D5FEF571 /* Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
2E61B6A0DB0F436A9DDBE86F /* Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@@ -1668,21 +1654,6 @@
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests-resources.sh\"\n";
showEnvVarsInLog = 0;
};
5ADEA7587189397768F2B36C /* Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */

View File

@@ -14,7 +14,8 @@
*/
@interface ASCollectionNode : ASDisplayNode
- (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout;
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout;
@property (nonatomic, readonly) ASCollectionView *view;

View File

@@ -9,6 +9,10 @@
#import "ASCollectionNode.h"
#import "ASDisplayNode+Subclasses.h"
@interface ASCollectionView (Internal)
- (instancetype)_initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout;
@end
@implementation ASCollectionNode
- (instancetype)init
@@ -20,7 +24,12 @@
- (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout
{
if (self = [super initWithViewBlock:^UIView *{ return [[ASCollectionView alloc] initWithCollectionViewLayout:layout]; }]) {
return [self initWithFrame:CGRectZero collectionViewLayout:layout];
}
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout
{
if (self = [super initWithViewBlock:^UIView *{ return [[ASCollectionView alloc] _initWithFrame:frame collectionViewLayout:layout]; }]) {
return self;
}
return nil;
@@ -31,6 +40,11 @@
return (ASCollectionView *)[super view];
}
- (void)visibilityDidChange:(BOOL)isVisible
{
}
- (void)clearContents
{
[super clearContents];

View File

@@ -12,7 +12,7 @@
#import <AsyncDisplayKit/ASCollectionViewProtocols.h>
#import <AsyncDisplayKit/ASBaseDefines.h>
#import <AsyncDisplayKit/ASBatchContext.h>
#import <AsyncDisplayKit/ASCollectionViewFlowLayoutInspector.h>
@class ASCellNode;
@protocol ASCollectionViewDataSource;
@@ -27,7 +27,13 @@
*/
@interface ASCollectionView : UICollectionView
/**
* Initializer.
*
* @param layout The layout object to use for organizing items. The collection view stores a strong reference to the specified object. Must not be nil.
*/
- (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout;
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout;
@property (nonatomic, weak) id<ASCollectionViewDataSource> asyncDataSource;
@property (nonatomic, weak) id<ASCollectionViewDelegate> asyncDelegate; // must not be nil
@@ -52,27 +58,6 @@
*/
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType;
/**
* Initializer.
*
* @param frame The frame rectangle for the collection view, measured in points. The origin of the frame is relative to the superview
* in which you plan to add it. This frame is passed to the superclass during initialization.
*
* @param layout The layout object to use for organizing items. The collection view stores a strong reference to the specified object.
* Must not be nil.
*
* @param asyncDataFetchingEnabled Enable the data fetching in async mode.
*
* @discussion If asyncDataFetching is enabled, the `ASCollectionView` will fetch data through `collectionView:numberOfRowsInSection:` and
* `collectionView:nodeForRowAtIndexPath:` in async mode from background thread. Otherwise, the methods will be invoked synchronically
* from calling thread.
* Enabling asyncDataFetching could avoid blocking main thread for `ASCellNode` allocation, which is frequently reported issue for
* large scale data. On another hand, the application code need take the responsibility to avoid data inconsistence. Specifically,
* we will lock the data source through `collectionViewLockDataSource`, and unlock it by `collectionViewUnlockDataSource` after the data fetching.
* The application should not update the data source while the data source is locked, to keep data consistence.
*/
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout asyncDataFetching:(BOOL)asyncDataFetchingEnabled;
/**
* The number of screens left to scroll before the delegate -collectionView:beginBatchFetchingWithContext: is called.
*
@@ -429,4 +414,10 @@
*/
- (CGSize)collectionView:(ASCollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section;
@end
@end
@interface ASCollectionView (Deprecated)
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout asyncDataFetching:(BOOL)asyncDataFetchingEnabled ASDISPLAYNODE_DEPRECATED;
@end

View File

@@ -9,6 +9,7 @@
#import "ASAssert.h"
#import "ASBatchFetching.h"
#import "ASCollectionView.h"
#import "ASCollectionNode.h"
#import "ASCollectionDataController.h"
#import "ASCollectionViewLayoutController.h"
#import "ASCollectionViewFlowLayoutInspector.h"
@@ -31,7 +32,7 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
*/
static BOOL _isInterceptedSelector(SEL sel)
{
return (
return (
// handled by ASCollectionView node<->cell machinery
sel == @selector(collectionView:cellForItemAtIndexPath:) ||
sel == @selector(collectionView:layout:sizeForItemAtIndexPath:) ||
@@ -44,7 +45,7 @@ static BOOL _isInterceptedSelector(SEL sel)
// used for ASRangeController visibility updates
sel == @selector(collectionView:willDisplayCell:forItemAtIndexPath:) ||
sel == @selector(collectionView:didEndDisplayingCell:forItemAtIndexPath:) ||
// used for batch fetching API
sel == @selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)
);
@@ -70,7 +71,7 @@ static BOOL _isInterceptedSelector(SEL sel)
if (!self) {
return nil;
}
ASDisplayNodeAssert(target, @"target must not be nil");
ASDisplayNodeAssert(interceptor, @"interceptor must not be nil");
@@ -84,7 +85,7 @@ static BOOL _isInterceptedSelector(SEL sel)
{
ASDisplayNodeAssert(_target, @"target must not be nil"); // catch weak ref's being nilled early
ASDisplayNodeAssert(_interceptor, @"interceptor must not be nil");
return (_isInterceptedSelector(aSelector) || [_target respondsToSelector:aSelector]);
}
@@ -92,7 +93,7 @@ static BOOL _isInterceptedSelector(SEL sel)
{
ASDisplayNodeAssert(_target, @"target must not be nil"); // catch weak ref's being nilled early
ASDisplayNodeAssert(_interceptor, @"interceptor must not be nil");
if (_isInterceptedSelector(aSelector)) {
return _interceptor;
}
@@ -140,21 +141,21 @@ static BOOL _isInterceptedSelector(SEL sel)
@interface ASCollectionView () <ASRangeControllerDataSource, ASRangeControllerDelegate, ASDataControllerSource, ASCellNodeLayoutDelegate> {
_ASCollectionViewProxy *_proxyDataSource;
_ASCollectionViewProxy *_proxyDelegate;
ASCollectionDataController *_dataController;
ASRangeController *_rangeController;
ASCollectionViewLayoutController *_layoutController;
ASCollectionViewFlowLayoutInspector *_flowLayoutInspector;
BOOL _performingBatchUpdates;
NSMutableArray *_batchUpdateBlocks;
BOOL _asyncDataFetchingEnabled;
BOOL _asyncDelegateImplementsInsetSection;
BOOL _collectionViewLayoutImplementsInsetSection;
BOOL _asyncDataSourceImplementsConstrainedSizeForNode;
BOOL _queuedNodeSizeUpdate;
ASBatchContext *_batchContext;
CGSize _maxSizeForNodesConstrainedSize;
@@ -172,7 +173,7 @@ static BOOL _isInterceptedSelector(SEL sel)
* You will get an assertion failure saying `Invalid number of items in section 0.
* The number of items after the update (1) must be equal to the number of items before the update (1) plus or minus the items added and removed (1 added, 0 removed).`
* The collection view never queried your data source before the update to see that it actually had 0 items.
*/
*/
BOOL _superIsPendingDataLoad;
}
@@ -187,48 +188,51 @@ static BOOL _isInterceptedSelector(SEL sel)
- (instancetype)initWithCollectionViewLayout:(UICollectionViewLayout *)layout
{
return [self initWithFrame:CGRectZero collectionViewLayout:layout asyncDataFetching:NO];
return [self initWithFrame:CGRectZero collectionViewLayout:layout];
}
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout
{
return [self initWithFrame:frame collectionViewLayout:layout asyncDataFetching:NO];
ASCollectionNode *collectionNode = [[ASCollectionNode alloc] initWithFrame:frame collectionViewLayout:layout];
return collectionNode.view;
}
// FIXME: This method is deprecated and will probably be removed in or shortly after 2.0.
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout asyncDataFetching:(BOOL)asyncDataFetchingEnabled
{
return [self initWithFrame:frame collectionViewLayout:layout];
}
- (instancetype)_initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout
{
if (!(self = [super initWithFrame:frame collectionViewLayout:layout]))
return nil;
// FIXME: asyncDataFetching is currently unreliable for some use cases.
// https://github.com/facebook/AsyncDisplayKit/issues/385
asyncDataFetchingEnabled = NO;
_layoutController = [[ASCollectionViewLayoutController alloc] initWithCollectionView:self];
_rangeController = [[ASRangeController alloc] init];
_rangeController.dataSource = self;
_rangeController.delegate = self;
_rangeController.layoutController = _layoutController;
_dataController = [[ASCollectionDataController alloc] initWithAsyncDataFetching:asyncDataFetchingEnabled];
_dataController = [[ASCollectionDataController alloc] initWithAsyncDataFetching:NO];
_dataController.delegate = _rangeController;
_dataController.dataSource = self;
_batchContext = [[ASBatchContext alloc] init];
_leadingScreensForBatching = 1.0;
_asyncDataFetchingEnabled = asyncDataFetchingEnabled;
_asyncDataFetchingEnabled = NO;
_asyncDataSourceLocked = NO;
_performingBatchUpdates = NO;
_batchUpdateBlocks = [NSMutableArray array];
_superIsPendingDataLoad = YES;
_collectionViewLayoutImplementsInsetSection = [layout respondsToSelector:@selector(sectionInset)];
_maxSizeForNodesConstrainedSize = self.bounds.size;
// If the initial size is 0, expect a size change very soon which is part of the initial configuration
// and should not trigger a relayout.
@@ -262,13 +266,13 @@ static BOOL _isInterceptedSelector(SEL sel)
*/
- (ASCollectionViewFlowLayoutInspector *)flowLayoutInspector
{
if (_flowLayoutInspector == nil) {
UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionViewLayout;
ASDisplayNodeAssertNotNil(layout, @"Collection view layout must be a flow layout to use the built-in inspector");
_flowLayoutInspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:self
flowLayout:layout];
}
return _flowLayoutInspector;
if (_flowLayoutInspector == nil) {
UICollectionViewFlowLayout *layout = (UICollectionViewFlowLayout *)self.collectionViewLayout;
ASDisplayNodeAssertNotNil(layout, @"Collection view layout must be a flow layout to use the built-in inspector");
_flowLayoutInspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:self
flowLayout:layout];
}
return _flowLayoutInspector;
}
#pragma mark -
@@ -314,7 +318,7 @@ static BOOL _isInterceptedSelector(SEL sel)
// the (common) case of nilling the asyncDataSource in the ViewController's dealloc. In this case our _asyncDataSource
// will return as nil (ARC magic) even though the _proxyDataSource still exists. It's really important to nil out
// super.dataSource in this case because calls to _ASTableViewProxy will start failing and cause crashes.
if (asyncDataSource == nil) {
super.dataSource = nil;
_asyncDataSource = nil;
@@ -334,7 +338,7 @@ static BOOL _isInterceptedSelector(SEL sel)
// the (common) case of nilling the asyncDelegate in the ViewController's dealloc. In this case our _asyncDelegate
// will return as nil (ARC magic) even though the _proxyDelegate still exists. It's really important to nil out
// super.delegate in this case because calls to _ASTableViewProxy will start failing and cause crashes.
if (asyncDelegate == nil) {
// order is important here, the delegate must be callable while nilling super.delegate to avoid random crashes
// in UIScrollViewAccessibility.
@@ -348,7 +352,7 @@ static BOOL _isInterceptedSelector(SEL sel)
super.delegate = (id<UICollectionViewDelegate>)_proxyDelegate;
_asyncDelegateImplementsInsetSection = ([_asyncDelegate respondsToSelector:@selector(collectionView:layout:insetForSectionAtIndex:)] ? 1 : 0);
}
[_layoutInspector didChangeCollectionViewDelegate:asyncDelegate];
}
@@ -409,7 +413,7 @@ static BOOL _isInterceptedSelector(SEL sel)
- (void)performBatchAnimated:(BOOL)animated updates:(void (^)())updates completion:(void (^)(BOOL))completion
{
ASDisplayNodeAssertMainThread();
[_dataController beginUpdates];
updates();
[_dataController endUpdatesAnimated:animated completion:completion];
@@ -487,7 +491,7 @@ static BOOL _isInterceptedSelector(SEL sel)
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
_ASCollectionViewCell *cell = [self dequeueReusableCellWithReuseIdentifier:kCellReuseIdentifier forIndexPath:indexPath];
ASCellNode *node = [_dataController nodeAtIndexPath:indexPath];
cell.node = node;
[_rangeController configureContentView:cell.contentView forCellNode:node];
@@ -524,7 +528,7 @@ static BOOL _isInterceptedSelector(SEL sel)
CGPoint scrollVelocity = [self.panGestureRecognizer velocityInView:self.superview];
return [self scrollDirectionForVelocity:scrollVelocity];
}
- (ASScrollDirection)scrollDirectionForVelocity:(CGPoint)scrollVelocity
{
ASScrollDirection direction = ASScrollDirectionNone;
@@ -544,7 +548,7 @@ static BOOL _isInterceptedSelector(SEL sel)
direction |= ASScrollDirectionUp;
}
}
return direction;
}
@@ -623,7 +627,7 @@ static BOOL _isInterceptedSelector(SEL sel)
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
[self handleBatchFetchScrollingToOffset:*targetContentOffset];
if ([_asyncDelegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) {
[_asyncDelegate scrollViewWillEndDragging:scrollView withVelocity:velocity targetContentOffset:targetContentOffset];
}
@@ -643,11 +647,11 @@ static BOOL _isInterceptedSelector(SEL sel)
- (void)handleBatchFetchScrollingToOffset:(CGPoint)targetOffset
{
ASDisplayNodeAssert(_batchContext != nil, @"Batch context should exist");
if (![self shouldBatchFetch]) {
return;
}
if (ASDisplayShouldFetchBatchForContext(_batchContext, [self scrollDirection], self.bounds, self.contentSize, targetOffset, _leadingScreensForBatching)) {
[_batchContext beginBatchFetching];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@@ -695,7 +699,7 @@ static BOOL _isInterceptedSelector(SEL sel)
}
constrainedSize = ASSizeRangeMake(CGSizeZero, maxSize);
}
UIEdgeInsets sectionInset = UIEdgeInsetsZero;
if (_collectionViewLayoutImplementsInsetSection) {
sectionInset = [(UICollectionViewFlowLayout *)self.collectionViewLayout sectionInset];
@@ -704,7 +708,7 @@ static BOOL _isInterceptedSelector(SEL sel)
if (_asyncDelegateImplementsInsetSection) {
sectionInset = [(id<ASCollectionViewDelegateFlowLayout>)_asyncDelegate collectionView:self layout:self.collectionViewLayout insetForSectionAtIndex:indexPath.section];
}
if (ASScrollDirectionContainsHorizontalDirection([self scrollableDirections])) {
constrainedSize.min.width = MAX(0, constrainedSize.min.width - sectionInset.left - sectionInset.right);
//ignore insets for FLT_MAX so FLT_MAX can be compared against
@@ -718,7 +722,7 @@ static BOOL _isInterceptedSelector(SEL sel)
constrainedSize.max.height = MAX(0, constrainedSize.max.height - sectionInset.top - sectionInset.bottom);
}
}
return constrainedSize;
}
@@ -738,7 +742,7 @@ static BOOL _isInterceptedSelector(SEL sel)
- (void)dataControllerLockDataSource
{
ASDisplayNodeAssert(!self.asyncDataSourceLocked, @"The data source has already been locked");
self.asyncDataSourceLocked = YES;
if ([_asyncDataSource respondsToSelector:@selector(collectionViewLockDataSource:)]) {
[_asyncDataSource collectionViewLockDataSource:self];
@@ -748,7 +752,7 @@ static BOOL _isInterceptedSelector(SEL sel)
- (void)dataControllerUnlockDataSource
{
ASDisplayNodeAssert(self.asyncDataSourceLocked, @"The data source has already been unlocked");
self.asyncDataSourceLocked = NO;
if ([_asyncDataSource respondsToSelector:@selector(collectionViewUnlockDataSource:)]) {
[_asyncDataSource collectionViewUnlockDataSource:self];
@@ -817,7 +821,7 @@ static BOOL _isInterceptedSelector(SEL sel)
- (void)rangeController:(ASRangeController *)rangeController didEndUpdatesAnimated:(BOOL)animated completion:(void (^)(BOOL))completion
{
ASDisplayNodeAssertMainThread();
if (!self.asyncDataSource || _superIsPendingDataLoad) {
if (completion) {
completion(NO);
@@ -832,7 +836,7 @@ static BOOL _isInterceptedSelector(SEL sel)
}
} completion:completion];
});
[_batchUpdateBlocks removeAllObjects];
_performingBatchUpdates = NO;
}
@@ -840,11 +844,11 @@ static BOOL _isInterceptedSelector(SEL sel)
- (void)rangeController:(ASRangeController *)rangeController didInsertNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
{
ASDisplayNodeAssertMainThread();
if (!self.asyncDataSource || _superIsPendingDataLoad) {
return; // if the asyncDataSource has become invalid while we are processing, ignore this request to avoid crashes
}
if (_performingBatchUpdates) {
[_batchUpdateBlocks addObject:^{
[super insertItemsAtIndexPaths:indexPaths];
@@ -859,11 +863,11 @@ static BOOL _isInterceptedSelector(SEL sel)
- (void)rangeController:(ASRangeController *)rangeController didDeleteNodes:(NSArray *)nodes atIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
{
ASDisplayNodeAssertMainThread();
if (!self.asyncDataSource || _superIsPendingDataLoad) {
return; // if the asyncDataSource has become invalid while we are processing, ignore this request to avoid crashes
}
if (_performingBatchUpdates) {
[_batchUpdateBlocks addObject:^{
[super deleteItemsAtIndexPaths:indexPaths];
@@ -878,11 +882,11 @@ static BOOL _isInterceptedSelector(SEL sel)
- (void)rangeController:(ASRangeController *)rangeController didInsertSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
{
ASDisplayNodeAssertMainThread();
if (!self.asyncDataSource || _superIsPendingDataLoad) {
return; // if the asyncDataSource has become invalid while we are processing, ignore this request to avoid crashes
}
if (_performingBatchUpdates) {
[_batchUpdateBlocks addObject:^{
[super insertSections:indexSet];
@@ -897,11 +901,11 @@ static BOOL _isInterceptedSelector(SEL sel)
- (void)rangeController:(ASRangeController *)rangeController didDeleteSectionsAtIndexSet:(NSIndexSet *)indexSet withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
{
ASDisplayNodeAssertMainThread();
if (!self.asyncDataSource || _superIsPendingDataLoad) {
return; // if the asyncDataSource has become invalid while we are processing, ignore this request to avoid crashes
}
if (_performingBatchUpdates) {
[_batchUpdateBlocks addObject:^{
[super deleteSections:indexSet];
@@ -918,11 +922,11 @@ static BOOL _isInterceptedSelector(SEL sel)
- (void)nodeDidRelayout:(ASCellNode *)node sizeChanged:(BOOL)sizeChanged
{
ASDisplayNodeAssertMainThread();
if (!sizeChanged || _queuedNodeSizeUpdate) {
return;
}
_queuedNodeSizeUpdate = YES;
[self performSelector:@selector(requeryNodeSizes)
withObject:nil
@@ -934,7 +938,7 @@ static BOOL _isInterceptedSelector(SEL sel)
- (void)requeryNodeSizes
{
_queuedNodeSizeUpdate = NO;
[super performBatchUpdates:^{} completion:nil];
}
@@ -944,7 +948,7 @@ static BOOL _isInterceptedSelector(SEL sel)
{
for (NSArray *section in [_dataController completedNodes]) {
for (ASDisplayNode *node in section) {
[node recursivelyClearContents];
[node exitInterfaceState:ASInterfaceStateDisplay];
}
}
}
@@ -953,7 +957,7 @@ static BOOL _isInterceptedSelector(SEL sel)
{
for (NSArray *section in [_dataController completedNodes]) {
for (ASDisplayNode *node in section) {
[node recursivelyClearFetchedData];
[node exitInterfaceState:ASInterfaceStateFetchData];
}
}
}

View File

@@ -37,35 +37,8 @@
@interface ASDisplayNode (Subclassing)
/** @name View Configuration */
/**
* @return The view class to use when creating a new display node instance. Defaults to _ASDisplayView.
*/
+ (Class)viewClass;
/** @name Properties */
/**
* @abstract The scale factor to apply to the rendering.
*
* @discussion Use setNeedsDisplayAtScale: to set a value and then after display, the display node will set the layer's
* contentsScale. This is to prevent jumps when re-rasterizing at a different contentsScale.
* Read this property if you need to know the future contentsScale of your layer, eg in drawParameters.
*
* @see setNeedsDisplayAtScale:
*/
@property (nonatomic, assign, readonly) CGFloat contentsScaleForDisplay;
/**
* @abstract Whether the view or layer of this display node is currently in a window
*/
@property (nonatomic, readonly, assign, getter=isInHierarchy) BOOL inHierarchy;
/**
* @abstract Return the calculated layout.
*
@@ -190,10 +163,9 @@
*
* @note Called on the display queue and/or main queue (MUST BE THREAD SAFE)
*/
+ (void)drawRect:(CGRect)bounds
withParameters:(id<NSObject>)parameters
isCancelled:(asdisplaynode_iscancelled_block_t)isCancelledBlock
isRasterizing:(BOOL)isRasterizing;
+ (void)drawRect:(CGRect)bounds withParameters:(id<NSObject>)parameters
isCancelled:(asdisplaynode_iscancelled_block_t)isCancelledBlock
isRasterizing:(BOOL)isRasterizing;
/**
* @summary Delegate override to provide new layer contents as a UIImage.
@@ -236,6 +208,33 @@
*/
- (void)displayDidFinish ASDISPLAYNODE_REQUIRES_SUPER;
/** @name Observing node-related changes */
/**
* @abstract Called whenever any bit in the ASInterfaceState bitfield is changed.
*
* @discussion Subclasses may use this to monitor when they become visible, should free cached data, and much more.
* @see ASInterfaceState
*/
- (void)interfaceStateDidChange:(ASInterfaceState)newState fromState:(ASInterfaceState)oldState;
- (void)visibilityDidChange:(BOOL)isVisible;
/**
* Called just before the view is added to a window.
*/
- (void)willEnterHierarchy ASDISPLAYNODE_REQUIRES_SUPER;
/**
* Called after the view is removed from the window.
*/
- (void)didExitHierarchy ASDISPLAYNODE_REQUIRES_SUPER;
/**
* @abstract Whether the view or layer of this display node is currently in a window
*/
@property (nonatomic, readonly, assign, getter=isInHierarchy) BOOL inHierarchy;
/**
* @abstract Indicates that the node should fetch any external data, such as images.
*
@@ -245,6 +244,23 @@
*/
- (void)fetchData ASDISPLAYNODE_REQUIRES_SUPER;
/**
* Provides an opportunity to clear any fetched data (e.g. remote / network or database-queried) on the current node.
*
* @discussion This will not clear data recursively for all subnodes. Either call -recursivelyClearFetchedData or
* selectively clear fetched data.
*/
- (void)clearFetchedData ASDISPLAYNODE_REQUIRES_SUPER;
/**
* Provides an opportunity to clear backing store and other memory-intensive intermediates, such as text layout managers
* on the current node.
*
* @discussion Called by -recursivelyClearContents. Base class implements self.contents = nil, clearing any backing
* store, for asynchronous regeneration when needed.
*/
- (void)clearContents ASDISPLAYNODE_REQUIRES_SUPER;
/**
* @abstract Indicates that the receiver is about to display its subnodes. This method is not called if there are no
* subnodes present.
@@ -267,7 +283,6 @@
*/
- (void)subnodeDisplayDidFinish:(ASDisplayNode *)subnode ASDISPLAYNODE_REQUIRES_SUPER;
/**
* @abstract Marks the receiver's bounds as needing to be redrawn, with a scale value.
*
@@ -295,6 +310,17 @@
*/
- (void)recursivelySetNeedsDisplayAtScale:(CGFloat)contentsScale;
/**
* @abstract The scale factor to apply to the rendering.
*
* @discussion Use setNeedsDisplayAtScale: to set a value and then after display, the display node will set the layer's
* contentsScale. This is to prevent jumps when re-rasterizing at a different contentsScale.
* Read this property if you need to know the future contentsScale of your layer, eg in drawParameters.
*
* @see setNeedsDisplayAtScale:
*/
@property (nonatomic, assign, readonly) CGFloat contentsScaleForDisplay;
/** @name Touch handling */
@@ -361,38 +387,6 @@
*/
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
/** @name Observing node-related changes */
/**
* Called just before the view is added to a window.
*/
- (void)willEnterHierarchy ASDISPLAYNODE_REQUIRES_SUPER;
/**
* Called after the view is removed from the window.
*/
- (void)didExitHierarchy ASDISPLAYNODE_REQUIRES_SUPER;
/**
* Provides an opportunity to clear backing store and other memory-intensive intermediates, such as text layout managers
* on the current node.
*
* @discussion Called by -recursivelyClearContents. Base class implements self.contents = nil, clearing any backing
* store, for asynchronous regeneration when needed.
*/
- (void)clearContents ASDISPLAYNODE_REQUIRES_SUPER;
/**
* Provides an opportunity to clear any fetched data (e.g. remote / network or database-queried) on the current node.
*
* @discussion This will not clear data recursively for all subnodes. Either call -recursivelyClearFetchedData or
* selectively clear fetched data.
*/
- (void)clearFetchedData ASDISPLAYNODE_REQUIRES_SUPER;
/** @name Placeholders */
/**
@@ -412,6 +406,7 @@
*/
- (UIImage *)placeholderImage;
/** @name Description */
/**

View File

@@ -1722,6 +1722,10 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
[self clearFetchedData];
}
- (void)visibilityDidChange:(BOOL)isVisible
{
}
/**
* We currently only set interface state on nodes in table/collection views. For other nodes, if they are
* in the hierarchy we enable all ASInterfaceState types with `ASInterfaceStateInHierarchy`, otherwise `None`.
@@ -1776,11 +1780,17 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
// Entered or exited data loading state.
if ((newState & ASInterfaceStateVisible) != (oldState & ASInterfaceStateVisible)) {
if (newState & ASInterfaceStateVisible) {
// Consider providing a -didBecomeVisible.
[self visibilityDidChange:YES];
} else {
// Consider providing a -didBecomeInvisible.
[self visibilityDidChange:NO];
}
}
[self interfaceStateDidChange:newState fromState:oldState];
}
- (void)interfaceStateDidChange:(ASInterfaceState)newState fromState:(ASInterfaceState)oldState
{
}
- (void)enterInterfaceState:(ASInterfaceState)interfaceState

View File

@@ -11,14 +11,23 @@
@interface ASViewController : UIViewController
- (instancetype)initWithNode:(ASDisplayNode *)node NS_DESIGNATED_INITIALIZER;
@property (nonatomic, strong, readonly) ASDisplayNode *node;
/**
* @abstract Passthrough property to the the .interfaceState of the node.
* @return The current ASInterfaceState of the node, indicating whether it is visible and other situational properties.
* @see ASInterfaceState
*/
@property (nonatomic, readonly) ASInterfaceState interfaceState;
// AsyncDisplayKit 2.0 BETA: This property is still being tested, but it allows
// blocking as a view controller becomes visible to ensure no placeholders flash onscreen.
// Refer to examples/SynchronousConcurrency, AsyncViewController.m
@property (nonatomic, assign) BOOL neverShowPlaceholders;
- (instancetype)initWithNode:(ASDisplayNode *)node;
/**
* The constrained size used to measure the backing node.

View File

@@ -16,6 +16,16 @@
BOOL _ensureDisplayed;
}
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
return [self initWithNode:nil];
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
return [self initWithNode:nil];
}
- (instancetype)initWithNode:(ASDisplayNode *)node
{
if (!(self = [super initWithNibName:nil bundle:nil])) {
@@ -65,4 +75,9 @@
return ASSizeRangeMake(viewSize, viewSize);
}
- (ASInterfaceState)interfaceState
{
return _node.interfaceState;
}
@end

View File

@@ -57,6 +57,9 @@ typedef NS_OPTIONS(NSUInteger, ASHierarchyState)
ASHierarchyState _hierarchyState;
}
// The view class to use when creating a new display node instance. Defaults to _ASDisplayView.
+ (Class)viewClass;
// These methods are recursive, and either union or remove the provided interfaceState to all sub-elements.
- (void)enterInterfaceState:(ASInterfaceState)interfaceState;
- (void)exitInterfaceState:(ASInterfaceState)interfaceState;

View File

@@ -1,5 +1,5 @@
//
// ASBasicImageDownloaderTests.m
// ASZBasicImageDownloaderTests.m
// AsyncDisplayKit
//
// Created by Victor Mayorov on 10/06/15.
@@ -10,11 +10,12 @@
#import <AsyncDisplayKit/ASBasicImageDownloader.h>
@interface ASBasicImageDownloaderTests : XCTestCase
// Z in the name to delay running until after the test instance is operating normally.
@interface ASZBasicImageDownloaderTests : XCTestCase
@end
@implementation ASBasicImageDownloaderTests
@implementation ASZBasicImageDownloaderTests
- (void)testAsynchronouslyDownloadTheSameURLTwice
{

View File

@@ -100,7 +100,7 @@
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
CGRect rect = CGRectMake(0, 0, 100.0, 100.0);
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout asyncDataFetching:NO];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout];
collectionView.asyncDataSource = dataSource;
collectionView.asyncDelegate = delegate;
@@ -122,7 +122,7 @@
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
CGRect rect = CGRectMake(0, 0, 100.0, 100.0);
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout asyncDataFetching:NO];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout];
collectionView.asyncDataSource = dataSource;
collectionView.asyncDelegate = delegate;
@@ -146,7 +146,7 @@
layout.headerReferenceSize = CGSizeMake(125.0, 125.0);
CGRect rect = CGRectMake(0, 0, 100.0, 100.0);
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout asyncDataFetching:NO];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout];
collectionView.asyncDataSource = dataSource;
ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout];
@@ -167,7 +167,7 @@
layout.footerReferenceSize = CGSizeMake(125.0, 125.0);
CGRect rect = CGRectMake(0, 0, 100.0, 100.0);
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout asyncDataFetching:NO];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout];
collectionView.asyncDataSource = dataSource;
ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout];
@@ -190,7 +190,7 @@
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
CGRect rect = CGRectMake(0, 0, 100.0, 100.0);
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout asyncDataFetching:NO];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout];
collectionView.asyncDataSource = dataSource;
collectionView.asyncDelegate = delegate;
@@ -212,7 +212,7 @@
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
CGRect rect = CGRectMake(0, 0, 100.0, 100.0);
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout asyncDataFetching:NO];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout];
collectionView.asyncDataSource = dataSource;
collectionView.asyncDelegate = delegate;
@@ -236,7 +236,7 @@
layout.headerReferenceSize = CGSizeMake(125.0, 125.0);
CGRect rect = CGRectMake(0, 0, 100.0, 100.0);
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout asyncDataFetching:NO];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout];
collectionView.asyncDataSource = dataSource;
ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout];
@@ -257,7 +257,7 @@
layout.footerReferenceSize = CGSizeMake(125.0, 125.0);
CGRect rect = CGRectMake(0, 0, 100.0, 100.0);
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout asyncDataFetching:NO];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:rect collectionViewLayout:layout];
collectionView.asyncDataSource = dataSource;
ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout];
@@ -274,7 +274,7 @@
InspectorTestDataSource *dataSource = [[InspectorTestDataSource alloc] init];
HeaderReferenceSizeTestDelegate *delegate = [[HeaderReferenceSizeTestDelegate alloc] init];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout asyncDataFetching:NO];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
collectionView.asyncDataSource = dataSource;
collectionView.asyncDelegate = delegate;
ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout];
@@ -291,7 +291,7 @@
- (void)testThatItRespondsWithTheDefaultNumberOfSections
{
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout asyncDataFetching:NO];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout];
NSUInteger sections = [inspector collectionView:collectionView numberOfSectionsForSupplementaryNodeOfKind:UICollectionElementKindSectionHeader];
XCTAssert(sections == 1, @"should return 1 by default");
@@ -304,7 +304,7 @@
{
InspectorTestDataSource *dataSource = [[InspectorTestDataSource alloc] init];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout asyncDataFetching:NO];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
collectionView.asyncDataSource = dataSource;
ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout];
NSUInteger sections = [inspector collectionView:collectionView numberOfSectionsForSupplementaryNodeOfKind:UICollectionElementKindSectionHeader];
@@ -321,7 +321,7 @@
InspectorTestDataSource *dataSource = [[InspectorTestDataSource alloc] init];
HeaderReferenceSizeTestDelegate *delegate = [[HeaderReferenceSizeTestDelegate alloc] init];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout asyncDataFetching:NO];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
collectionView.asyncDataSource = dataSource;
collectionView.asyncDelegate = delegate;
ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout];
@@ -338,7 +338,7 @@
HeaderReferenceSizeTestDelegate *delegate = [[HeaderReferenceSizeTestDelegate alloc] init];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.footerReferenceSize = CGSizeMake(125.0, 125.0);
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout asyncDataFetching:NO];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
collectionView.asyncDataSource = dataSource;
collectionView.asyncDelegate = delegate;
ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout];
@@ -354,7 +354,7 @@
InspectorTestDataSource *dataSource = [[InspectorTestDataSource alloc] init];
HeaderReferenceSizeTestDelegate *delegate = [[HeaderReferenceSizeTestDelegate alloc] init];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout asyncDataFetching:NO];
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
collectionView.asyncDataSource = dataSource;
collectionView.asyncDelegate = delegate;
ASCollectionViewFlowLayoutInspector *inspector = [[ASCollectionViewFlowLayoutInspector alloc] initWithCollectionView:collectionView flowLayout:layout];

View File

@@ -130,7 +130,6 @@
AC3C4A5B1A11F47200143C57 /* Frameworks */,
AC3C4A5C1A11F47200143C57 /* Resources */,
A6902C454C7661D0D277AC62 /* Copy Pods Resources */,
EC37EEC9933F5786936BFE7C /* Embed Pods Frameworks */,
);
buildRules = (
);
@@ -201,21 +200,6 @@
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
showEnvVarsInLog = 0;
};
EC37EEC9933F5786936BFE7C /* Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
F868CFBB21824CC9521B6588 /* Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;