Merge commit '3ccc2f0f15d2e4ed7105f0ef6aea575e05cfd7ad'

# Conflicts:
#	AsyncDisplayKit.xcodeproj/project.pbxproj
#	Source/ASDisplayNode.mm
#	Source/ASMapNode.mm
#	Source/Details/ASDataController.mm
#	Source/Details/ASPINRemoteImageDownloader.h
#	Source/Details/ASPINRemoteImageDownloader.m
This commit is contained in:
Peter
2017-08-04 13:12:06 +03:00
987 changed files with 94742 additions and 8450 deletions

View File

@@ -1,27 +1,35 @@
//
// ASCollectionNode.mm
// AsyncDisplayKit
//
// Created by Scott Goodson on 9/5/15.
// Texture
//
// Copyright (c) 2014-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.
// LICENSE file in the /ASDK-Licenses directory of this source tree. An additional
// grant of patent rights can be found in the PATENTS file in the same directory.
//
// Modifications to this file made after 4/13/2017 are: Copyright (c) 2017-present,
// Pinterest, Inc. Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
#ifndef MINIMAL_ASDK
#import <AsyncDisplayKit/ASCollectionNode.h>
#import <AsyncDisplayKit/ASCollectionNode+Beta.h>
#import <AsyncDisplayKit/ASCollectionElement.h>
#import <AsyncDisplayKit/ASElementMap.h>
#import <AsyncDisplayKit/ASCollectionInternal.h>
#import <AsyncDisplayKit/ASCollectionLayout.h>
#import <AsyncDisplayKit/ASCollectionViewLayoutFacilitatorProtocol.h>
#import <AsyncDisplayKit/ASDisplayNode+Beta.h>
#import <AsyncDisplayKit/ASDisplayNode+Subclasses.h>
#import <AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h>
#import <AsyncDisplayKit/ASInternalHelpers.h>
#import <AsyncDisplayKit/ASCellNode+Internal.h>
#import <AsyncDisplayKit/_ASHierarchyChangeSet.h>
#import <AsyncDisplayKit/AsyncDisplayKit+Debug.h>
#import <AsyncDisplayKit/ASSectionContext.h>
#import <AsyncDisplayKit/ASDataController.h>
@@ -34,10 +42,14 @@
@interface _ASCollectionPendingState : NSObject
@property (weak, nonatomic) id <ASCollectionDelegate> delegate;
@property (weak, nonatomic) id <ASCollectionDataSource> dataSource;
@property (strong, nonatomic) UICollectionViewLayout *collectionViewLayout;
@property (nonatomic, assign) ASLayoutRangeMode rangeMode;
@property (nonatomic, assign) BOOL allowsSelection; // default is YES
@property (nonatomic, assign) BOOL allowsMultipleSelection; // default is NO
@property (nonatomic, assign) BOOL inverted; //default is NO
@property (nonatomic, assign) BOOL usesSynchronousDataLoading;
@property (nonatomic, assign) CGFloat leadingScreensForBatching;
@property (weak, nonatomic) id <ASCollectionViewLayoutInspecting> layoutInspector;
@end
@implementation _ASCollectionPendingState
@@ -102,6 +114,7 @@
{
ASDN::RecursiveMutex _environmentStateLock;
Class _collectionViewClass;
id<ASBatchFetchingDelegate> _batchFetchingDelegate;
}
@property (nonatomic) _ASCollectionPendingState *pendingState;
@end
@@ -134,13 +147,21 @@
return [self initWithFrame:frame collectionViewLayout:layout layoutFacilitator:nil];
}
- (instancetype)initWithLayoutDelegate:(id<ASCollectionLayoutDelegate>)layoutDelegate layoutFacilitator:(id<ASCollectionViewLayoutFacilitatorProtocol>)layoutFacilitator
{
return [self initWithFrame:CGRectZero collectionViewLayout:[[ASCollectionLayout alloc] initWithLayoutDelegate:layoutDelegate] layoutFacilitator:layoutFacilitator];
}
- (instancetype)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout layoutFacilitator:(id<ASCollectionViewLayoutFacilitatorProtocol>)layoutFacilitator
{
if (self = [super init]) {
// Must call the setter here to make sure pendingState is created and the layout is configured.
[self setCollectionViewLayout:layout];
__weak __typeof__(self) weakSelf = self;
[self setViewBlock:^{
__typeof__(self) strongSelf = weakSelf;
return [[[strongSelf collectionViewClass] alloc] _initWithFrame:frame collectionViewLayout:layout layoutFacilitator:layoutFacilitator eventLog:ASDisplayNodeGetEventLog(strongSelf)];
return [[[strongSelf collectionViewClass] alloc] _initWithFrame:frame collectionViewLayout:strongSelf->_pendingState.collectionViewLayout layoutFacilitator:layoutFacilitator owningNode:strongSelf eventLog:ASDisplayNodeGetEventLog(strongSelf)];
}];
}
return self;
@@ -157,16 +178,20 @@
if (_pendingState) {
_ASCollectionPendingState *pendingState = _pendingState;
self.pendingState = nil;
view.asyncDelegate = pendingState.delegate;
view.asyncDataSource = pendingState.dataSource;
view.inverted = pendingState.inverted;
view.allowsSelection = pendingState.allowsSelection;
view.allowsMultipleSelection = pendingState.allowsMultipleSelection;
view.asyncDelegate = pendingState.delegate;
view.asyncDataSource = pendingState.dataSource;
view.inverted = pendingState.inverted;
view.allowsSelection = pendingState.allowsSelection;
view.allowsMultipleSelection = pendingState.allowsMultipleSelection;
view.usesSynchronousDataLoading = pendingState.usesSynchronousDataLoading;
view.layoutInspector = pendingState.layoutInspector;
self.pendingState = nil;
if (pendingState.rangeMode != ASLayoutRangeModeUnspecified) {
[view.rangeController updateCurrentRangeWithMode:pendingState.rangeMode];
}
// Don't need to set collectionViewLayout to the view as the layout was already used to init the view in view block.
}
}
@@ -181,18 +206,21 @@
[self.rangeController clearContents];
}
- (void)didExitPreloadState
{
[super didExitPreloadState];
[self.rangeController clearPreloadedData];
}
- (void)interfaceStateDidChange:(ASInterfaceState)newState fromState:(ASInterfaceState)oldState
{
[super interfaceStateDidChange:newState fromState:oldState];
[ASRangeController layoutDebugOverlayIfNeeded];
}
- (void)didEnterPreloadState
{
[super didEnterPreloadState];
// Intentionally allocate the view here and trigger a layout pass on it, which in turn will trigger the intial data load.
// We can get rid of this call later when ASDataController, ASRangeController and ASCollectionLayout can operate without the view.
// TODO (ASCL) If this node supports async layout, kick off the initial data load without allocating the view
[[self view] layoutIfNeeded];
}
#if ASRangeControllerLoggingEnabled
- (void)didEnterVisibleState
{
@@ -207,6 +235,12 @@
}
#endif
- (void)didExitPreloadState
{
[super didExitPreloadState];
[self.rangeController clearPreloadedData];
}
#pragma mark Setter / Getter
// TODO: Implement this without the view. Then revisit ASLayoutElementCollectionTableSetTraitCollection
@@ -250,6 +284,44 @@
}
}
- (void)setLayoutInspector:(id<ASCollectionViewLayoutInspecting>)layoutInspector
{
if ([self pendingState]) {
_pendingState.layoutInspector = layoutInspector;
} else {
ASDisplayNodeAssert([self isNodeLoaded], @"ASCollectionNode should be loaded if pendingState doesn't exist");
self.view.layoutInspector = layoutInspector;
}
}
- (id<ASCollectionViewLayoutInspecting>)layoutInspector
{
if ([self pendingState]) {
return _pendingState.layoutInspector;
} else {
return self.view.layoutInspector;
}
}
- (void)setLeadingScreensForBatching:(CGFloat)leadingScreensForBatching
{
if ([self pendingState]) {
_pendingState.leadingScreensForBatching = leadingScreensForBatching;
} else {
ASDisplayNodeAssert([self isNodeLoaded], @"ASCollectionNode should be loaded if pendingState doesn't exist");
self.view.leadingScreensForBatching = leadingScreensForBatching;
}
}
- (CGFloat)leadingScreensForBatching
{
if ([self pendingState]) {
return _pendingState.leadingScreensForBatching;
} else {
return self.view.leadingScreensForBatching;
}
}
- (void)setDelegate:(id <ASCollectionDelegate>)delegate
{
if ([self pendingState]) {
@@ -341,6 +413,80 @@
}
}
- (void)setCollectionViewLayout:(UICollectionViewLayout *)layout
{
if ([self pendingState]) {
[self _configureCollectionViewLayout:layout];
_pendingState.collectionViewLayout = layout;
} else {
[self _configureCollectionViewLayout:layout];
self.view.collectionViewLayout = layout;
}
}
- (UICollectionViewLayout *)collectionViewLayout
{
if ([self pendingState]) {
return _pendingState.collectionViewLayout;
} else {
return self.view.collectionViewLayout;
}
}
- (ASScrollDirection)scrollDirection
{
return [self isNodeLoaded] ? self.view.scrollDirection : ASScrollDirectionNone;
}
- (ASScrollDirection)scrollableDirections
{
return [self isNodeLoaded] ? self.view.scrollableDirections : ASScrollDirectionNone;
}
- (ASElementMap *)visibleElements
{
ASDisplayNodeAssertMainThread();
// TODO Own the data controller when view is not yet loaded
return self.dataController.visibleMap;
}
- (id<ASCollectionLayoutDelegate>)layoutDelegate
{
UICollectionViewLayout *layout = self.collectionViewLayout;
if ([layout isKindOfClass:[ASCollectionLayout class]]) {
return ((ASCollectionLayout *)layout).layoutDelegate;
}
return nil;
}
- (void)setBatchFetchingDelegate:(id<ASBatchFetchingDelegate>)batchFetchingDelegate
{
_batchFetchingDelegate = batchFetchingDelegate;
}
- (id<ASBatchFetchingDelegate>)batchFetchingDelegate
{
return _batchFetchingDelegate;
}
- (BOOL)usesSynchronousDataLoading
{
if ([self pendingState]) {
return _pendingState.usesSynchronousDataLoading;
} else {
return self.view.usesSynchronousDataLoading;
}
}
- (void)setUsesSynchronousDataLoading:(BOOL)usesSynchronousDataLoading
{
if ([self pendingState]) {
_pendingState.usesSynchronousDataLoading = usesSynchronousDataLoading;
} else {
self.view.usesSynchronousDataLoading = usesSynchronousDataLoading;
}
}
#pragma mark - Range Tuning
- (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType
@@ -447,6 +593,12 @@
return [self.dataController.pendingMap elementForItemAtIndexPath:indexPath].node;
}
- (id)viewModelForItemAtIndexPath:(NSIndexPath *)indexPath
{
[self reloadDataInitiallyIfNeeded];
return [self.dataController.pendingMap elementForItemAtIndexPath:indexPath].viewModel;
}
- (NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode
{
return [self.dataController.pendingMap indexPathForElement:cellNode.collectionElement];
@@ -533,9 +685,17 @@
- (void)reloadDataWithCompletion:(void (^)())completion
{
ASDisplayNodeAssertMainThread();
if (self.nodeLoaded) {
[self.view reloadDataWithCompletion:completion];
if (!self.nodeLoaded) {
return;
}
[self performBatchUpdates:^{
[self.view.changeSet reloadData];
} completion:^(BOOL finished){
if (completion) {
completion();
}
}];
}
- (void)reloadData
@@ -543,14 +703,19 @@
[self reloadDataWithCompletion:nil];
}
- (void)relayoutItems
{
[self.view relayoutItems];
}
- (void)reloadDataImmediately
{
[self.view reloadDataImmediately];
ASDisplayNodeAssertMainThread();
[self reloadData];
[self waitUntilAllUpdatesAreCommitted];
}
- (void)relayoutItems
{
ASDisplayNodeAssertMainThread();
if (self.nodeLoaded) {
[self.view relayoutItems];
}
}
- (void)beginUpdates
@@ -663,6 +828,16 @@ ASLayoutElementCollectionTableSetTraitCollection(_environmentStateLock)
return result;
}
#pragma mark - Private methods
- (void)_configureCollectionViewLayout:(UICollectionViewLayout *)layout
{
if ([layout isKindOfClass:[ASCollectionLayout class]]) {
ASCollectionLayout *collectionLayout = (ASCollectionLayout *)layout;
collectionLayout.collectionNode = self;
}
}
@end
#endif