mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-13 18:00:17 +00:00
Revert "update from master/"
This reverts commit d7fde61e168b6594ca5d74836597b0aac0e83e9b.
This commit is contained in:
parent
d7fde61e16
commit
3080ee33cf
@ -256,9 +256,9 @@
|
||||
68355B3A1CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 68355B361CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m */; };
|
||||
68355B3B1CB57A5A001D4E68 /* ASImageContainerProtocolCategories.h in Headers */ = {isa = PBXBuildFile; fileRef = 68355B371CB57A5A001D4E68 /* ASImageContainerProtocolCategories.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
68355B3C1CB57A5A001D4E68 /* ASImageContainerProtocolCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = 68355B381CB57A5A001D4E68 /* ASImageContainerProtocolCategories.m */; };
|
||||
68355B3D1CB57A5A001D4E68 /* ASPINRemoteImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = 68355B391CB57A5A001D4E68 /* ASPINRemoteImageDownloader.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
68355B3D1CB57A5A001D4E68 /* ASPINRemoteImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = 68355B391CB57A5A001D4E68 /* ASPINRemoteImageDownloader.h */; };
|
||||
68355B3E1CB57A60001D4E68 /* ASPINRemoteImageDownloader.m in Sources */ = {isa = PBXBuildFile; fileRef = 68355B361CB57A5A001D4E68 /* ASPINRemoteImageDownloader.m */; };
|
||||
68355B3F1CB57A64001D4E68 /* ASPINRemoteImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = 68355B391CB57A5A001D4E68 /* ASPINRemoteImageDownloader.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
68355B3F1CB57A64001D4E68 /* ASPINRemoteImageDownloader.h in Headers */ = {isa = PBXBuildFile; fileRef = 68355B391CB57A5A001D4E68 /* ASPINRemoteImageDownloader.h */; };
|
||||
68355B401CB57A69001D4E68 /* ASImageContainerProtocolCategories.m in Sources */ = {isa = PBXBuildFile; fileRef = 68355B381CB57A5A001D4E68 /* ASImageContainerProtocolCategories.m */; };
|
||||
68355B411CB57A6C001D4E68 /* ASImageContainerProtocolCategories.h in Headers */ = {isa = PBXBuildFile; fileRef = 68355B371CB57A5A001D4E68 /* ASImageContainerProtocolCategories.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
68AF37DB1CBEF4D80077BF76 /* ASImageNode+AnimatedImagePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 68B8A4DB1CBD911D007E4543 /* ASImageNode+AnimatedImagePrivate.h */; };
|
||||
@ -368,7 +368,6 @@
|
||||
9C8898BB1C738B9800D6B02E /* ASTextKitFontSizeAdjuster.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9C8898BA1C738B9800D6B02E /* ASTextKitFontSizeAdjuster.mm */; };
|
||||
9C8898BC1C738BA800D6B02E /* ASTextKitFontSizeAdjuster.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9C8898BA1C738B9800D6B02E /* ASTextKitFontSizeAdjuster.mm */; };
|
||||
9C8898BD1C738BB800D6B02E /* ASTextKitFontSizeAdjuster.h in Headers */ = {isa = PBXBuildFile; fileRef = A32FEDD31C501B6A004F642A /* ASTextKitFontSizeAdjuster.h */; };
|
||||
9CC606651D24DF9E006581A0 /* NSIndexSet+ASHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = CC4981BB1D1C7F65004E13CC /* NSIndexSet+ASHelpers.m */; };
|
||||
9CDC18CC1B910E12004965E2 /* ASLayoutablePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CDC18CB1B910E12004965E2 /* ASLayoutablePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
9CDC18CD1B910E12004965E2 /* ASLayoutablePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 9CDC18CB1B910E12004965E2 /* ASLayoutablePrivate.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
9CFFC6BE1CCAC52B006A6476 /* ASEnvironment.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9CFFC6BD1CCAC52B006A6476 /* ASEnvironment.mm */; };
|
||||
@ -547,13 +546,10 @@
|
||||
CC3B208E1C3F7D0A00798563 /* ASWeakSetTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC3B208D1C3F7D0A00798563 /* ASWeakSetTests.m */; };
|
||||
CC3B20901C3F892D00798563 /* ASBridgedPropertiesTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = CC3B208F1C3F892D00798563 /* ASBridgedPropertiesTests.mm */; };
|
||||
CC4981B31D1A02BE004E13CC /* ASTableViewThrashTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC4981B21D1A02BE004E13CC /* ASTableViewThrashTests.m */; };
|
||||
CC4981BC1D1C7F65004E13CC /* NSIndexSet+ASHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = CC4981BA1D1C7F65004E13CC /* NSIndexSet+ASHelpers.h */; };
|
||||
CC4981BD1D1C7F65004E13CC /* NSIndexSet+ASHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = CC4981BB1D1C7F65004E13CC /* NSIndexSet+ASHelpers.m */; };
|
||||
CC7FD9DE1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
CC7FD9DF1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */; };
|
||||
CC7FD9E11BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m */; };
|
||||
CC7FD9E21BB603FF005CCB2B /* ASPhotosFrameworkImageRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
CCF18FF41D2575E300DF5895 /* NSIndexSet+ASHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = CC4981BA1D1C7F65004E13CC /* NSIndexSet+ASHelpers.h */; };
|
||||
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 */; };
|
||||
DB55C2611C6408D6004EDCF5 /* _ASTransitionContext.h in Headers */ = {isa = PBXBuildFile; fileRef = DB55C25F1C6408D6004EDCF5 /* _ASTransitionContext.h */; };
|
||||
@ -941,8 +937,6 @@
|
||||
CC3B208D1C3F7D0A00798563 /* ASWeakSetTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASWeakSetTests.m; sourceTree = "<group>"; };
|
||||
CC3B208F1C3F892D00798563 /* ASBridgedPropertiesTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASBridgedPropertiesTests.mm; sourceTree = "<group>"; };
|
||||
CC4981B21D1A02BE004E13CC /* ASTableViewThrashTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASTableViewThrashTests.m; sourceTree = "<group>"; };
|
||||
CC4981BA1D1C7F65004E13CC /* NSIndexSet+ASHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSIndexSet+ASHelpers.h"; sourceTree = "<group>"; };
|
||||
CC4981BB1D1C7F65004E13CC /* NSIndexSet+ASHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSIndexSet+ASHelpers.m"; sourceTree = "<group>"; };
|
||||
CC7FD9DC1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASPhotosFrameworkImageRequest.h; sourceTree = "<group>"; };
|
||||
CC7FD9DD1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPhotosFrameworkImageRequest.m; sourceTree = "<group>"; };
|
||||
CC7FD9E01BB5F750005CCB2B /* ASPhotosFrameworkImageRequestTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASPhotosFrameworkImageRequestTests.m; sourceTree = "<group>"; };
|
||||
@ -1235,8 +1229,6 @@
|
||||
058D09E1195D050800B7D73C /* Details */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CC4981BA1D1C7F65004E13CC /* NSIndexSet+ASHelpers.h */,
|
||||
CC4981BB1D1C7F65004E13CC /* NSIndexSet+ASHelpers.m */,
|
||||
9CFFC6BD1CCAC52B006A6476 /* ASEnvironment.mm */,
|
||||
058D09E2195D050800B7D73C /* _ASDisplayLayer.h */,
|
||||
058D09E3195D050800B7D73C /* _ASDisplayLayer.mm */,
|
||||
@ -1642,7 +1634,6 @@
|
||||
ACF6ED2D1B17843500DA7C62 /* ASRatioLayoutSpec.h in Headers */,
|
||||
AC47D9451B3BB41900AAEE9D /* ASRelativeSize.h in Headers */,
|
||||
291B63FB1AA53A7A000A71B3 /* ASScrollDirection.h in Headers */,
|
||||
CC4981BC1D1C7F65004E13CC /* NSIndexSet+ASHelpers.h in Headers */,
|
||||
D785F6621A74327E00291744 /* ASScrollNode.h in Headers */,
|
||||
058D0A7F195D05F900B7D73C /* ASSentinel.h in Headers */,
|
||||
9C8221951BA237B80037F19A /* ASStackBaselinePositionedLayout.h in Headers */,
|
||||
@ -1801,7 +1792,6 @@
|
||||
254C6B741BF94DF4003EC431 /* ASTextNodeWordKerner.h in Headers */,
|
||||
DB55C2671C641AE4004EDCF5 /* ASContextTransitioning.h in Headers */,
|
||||
68B0277B1C1A79D60041016B /* ASDisplayNode+Beta.h in Headers */,
|
||||
CCF18FF41D2575E300DF5895 /* NSIndexSet+ASHelpers.h in Headers */,
|
||||
B350622D1B010EFD0018CF92 /* ASScrollDirection.h in Headers */,
|
||||
254C6B751BF94DF4003EC431 /* ASTextKitComponents.h in Headers */,
|
||||
B35062081B010EFD0018CF92 /* ASScrollNode.h in Headers */,
|
||||
@ -1884,12 +1874,12 @@
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 058D09D2195D04C000B7D73C /* Build configuration list for PBXNativeTarget "AsyncDisplayKitTests" */;
|
||||
buildPhases = (
|
||||
2E61B6A0DB0F436A9DDBE86F /* [CP] Check Pods Manifest.lock */,
|
||||
2E61B6A0DB0F436A9DDBE86F /* 📦 Check Pods Manifest.lock */,
|
||||
058D09B8195D04C000B7D73C /* Sources */,
|
||||
058D09B9195D04C000B7D73C /* Frameworks */,
|
||||
058D09BA195D04C000B7D73C /* Resources */,
|
||||
3B9D88CDF51B429C8409E4B6 /* [CP] Copy Pods Resources */,
|
||||
B130AB1AC0A1E5162E211C19 /* [CP] Embed Pods Frameworks */,
|
||||
3B9D88CDF51B429C8409E4B6 /* 📦 Copy Pods Resources */,
|
||||
B130AB1AC0A1E5162E211C19 /* 📦 Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@ -1990,14 +1980,14 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
2E61B6A0DB0F436A9DDBE86F /* [CP] Check Pods Manifest.lock */ = {
|
||||
2E61B6A0DB0F436A9DDBE86F /* 📦 Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
name = "📦 Check Pods Manifest.lock";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -2005,14 +1995,14 @@
|
||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
3B9D88CDF51B429C8409E4B6 /* [CP] Copy Pods Resources */ = {
|
||||
3B9D88CDF51B429C8409E4B6 /* 📦 Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
name = "📦 Copy Pods Resources";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -2020,14 +2010,14 @@
|
||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-AsyncDisplayKitTests/Pods-AsyncDisplayKitTests-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
B130AB1AC0A1E5162E211C19 /* [CP] Embed Pods Frameworks */ = {
|
||||
B130AB1AC0A1E5162E211C19 /* 📦 Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
name = "📦 Embed Pods Frameworks";
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -2111,7 +2101,6 @@
|
||||
ACF6ED4C1B17847A00DA7C62 /* ASInternalHelpers.mm in Sources */,
|
||||
68FC85DF1CE29AB700EDD713 /* ASNavigationController.m in Sources */,
|
||||
ACF6ED251B17843500DA7C62 /* ASLayout.mm in Sources */,
|
||||
CC4981BD1D1C7F65004E13CC /* NSIndexSet+ASHelpers.m in Sources */,
|
||||
DB55C2631C6408D6004EDCF5 /* _ASTransitionContext.m in Sources */,
|
||||
92074A631CC8BA1900918F75 /* ASImageNode+tvOS.m in Sources */,
|
||||
251B8EFA1BBB3D690087C538 /* ASCollectionViewFlowLayoutInspector.m in Sources */,
|
||||
@ -2277,7 +2266,6 @@
|
||||
CC3B208C1C3F7A5400798563 /* ASWeakSet.m in Sources */,
|
||||
B350621C1B010EFD0018CF92 /* ASFlowLayoutController.mm in Sources */,
|
||||
B350621E1B010EFD0018CF92 /* ASHighlightOverlayLayer.mm in Sources */,
|
||||
9CC606651D24DF9E006581A0 /* NSIndexSet+ASHelpers.m in Sources */,
|
||||
92074A641CC8BA1900918F75 /* ASImageNode+tvOS.m in Sources */,
|
||||
B35062541B010EFD0018CF92 /* ASImageNode+CGExtras.m in Sources */,
|
||||
68355B401CB57A69001D4E68 /* ASImageContainerProtocolCategories.m in Sources */,
|
||||
|
||||
@ -15,7 +15,6 @@
|
||||
#import "ASBackgroundLayoutSpec.h"
|
||||
#import "ASInsetLayoutSpec.h"
|
||||
#import "ASDisplayNode+Beta.h"
|
||||
#import "ASStaticLayoutSpec.h"
|
||||
|
||||
@interface ASButtonNode ()
|
||||
{
|
||||
@ -492,13 +491,9 @@
|
||||
spec = [ASInsetLayoutSpec insetLayoutSpecWithInsets:contentEdgeInsets child:spec];
|
||||
}
|
||||
|
||||
if (CGSizeEqualToSize(self.preferredFrameSize, CGSizeZero) == NO) {
|
||||
stack.sizeRange = ASRelativeSizeRangeMakeWithExactCGSize(self.preferredFrameSize);
|
||||
spec = [ASStaticLayoutSpec staticLayoutSpecWithChildren:@[stack]];
|
||||
}
|
||||
|
||||
if (_backgroundImageNode.image) {
|
||||
spec = [ASBackgroundLayoutSpec backgroundLayoutSpecWithChild:spec background:_backgroundImageNode];
|
||||
spec = [ASBackgroundLayoutSpec backgroundLayoutSpecWithChild:spec
|
||||
background:_backgroundImageNode];
|
||||
}
|
||||
|
||||
return spec;
|
||||
|
||||
@ -430,22 +430,22 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
|
||||
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeType:(ASLayoutRangeType)rangeType
|
||||
{
|
||||
[_rangeController setTuningParameters:tuningParameters forRangeMode:ASLayoutRangeModeFull rangeType:rangeType];
|
||||
[_collectionNode setTuningParameters:tuningParameters forRangeType:rangeType];
|
||||
}
|
||||
|
||||
- (ASRangeTuningParameters)tuningParametersForRangeType:(ASLayoutRangeType)rangeType
|
||||
{
|
||||
return [_rangeController tuningParametersForRangeMode:ASLayoutRangeModeFull rangeType:rangeType];
|
||||
return [_collectionNode tuningParametersForRangeType:rangeType];
|
||||
}
|
||||
|
||||
- (void)setTuningParameters:(ASRangeTuningParameters)tuningParameters forRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType
|
||||
{
|
||||
[_rangeController setTuningParameters:tuningParameters forRangeMode:rangeMode rangeType:rangeType];
|
||||
[_collectionNode setTuningParameters:tuningParameters forRangeMode:rangeMode rangeType:rangeType];
|
||||
}
|
||||
|
||||
- (ASRangeTuningParameters)tuningParametersForRangeMode:(ASLayoutRangeMode)rangeMode rangeType:(ASLayoutRangeType)rangeType
|
||||
{
|
||||
return [_rangeController tuningParametersForRangeMode:rangeMode rangeType:rangeType];
|
||||
return [_collectionNode tuningParametersForRangeMode:rangeMode rangeType:rangeType];
|
||||
}
|
||||
|
||||
- (CGSize)calculatedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
|
||||
@ -517,21 +517,18 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
- (void)insertSections:(NSIndexSet *)sections
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
if (sections.count == 0) { return; }
|
||||
[_dataController insertSections:sections withAnimationOptions:kASCollectionViewAnimationNone];
|
||||
}
|
||||
|
||||
- (void)deleteSections:(NSIndexSet *)sections
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
if (sections.count == 0) { return; }
|
||||
[_dataController deleteSections:sections withAnimationOptions:kASCollectionViewAnimationNone];
|
||||
}
|
||||
|
||||
- (void)reloadSections:(NSIndexSet *)sections
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
if (sections.count == 0) { return; }
|
||||
[_dataController reloadSections:sections withAnimationOptions:kASCollectionViewAnimationNone];
|
||||
}
|
||||
|
||||
@ -544,21 +541,18 @@ static NSString * const kCellReuseIdentifier = @"_ASCollectionViewCell";
|
||||
- (void)insertItemsAtIndexPaths:(NSArray *)indexPaths
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
if (indexPaths.count == 0) { return; }
|
||||
[_dataController insertRowsAtIndexPaths:indexPaths withAnimationOptions:kASCollectionViewAnimationNone];
|
||||
}
|
||||
|
||||
- (void)deleteItemsAtIndexPaths:(NSArray *)indexPaths
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
if (indexPaths.count == 0) { return; }
|
||||
[_dataController deleteRowsAtIndexPaths:indexPaths withAnimationOptions:kASCollectionViewAnimationNone];
|
||||
}
|
||||
|
||||
- (void)reloadItemsAtIndexPaths:(NSArray *)indexPaths
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
if (indexPaths.count == 0) { return; }
|
||||
[_dataController reloadRowsAtIndexPaths:indexPaths withAnimationOptions:kASCollectionViewAnimationNone];
|
||||
}
|
||||
|
||||
|
||||
@ -465,13 +465,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (NSString *)descriptionForRecursiveDescription;
|
||||
|
||||
/**
|
||||
* @abstract Called when the node's ASTraitCollection changes
|
||||
*
|
||||
* @discussion Subclasses can override this method to react to a trait collection change.
|
||||
*/
|
||||
- (void)asyncTraitCollectionDidChange;
|
||||
|
||||
@end
|
||||
|
||||
#define ASDisplayNodeAssertThreadAffinity(viewNode) ASDisplayNodeAssert(!viewNode || ASDisplayNodeThreadIsMain() || !(viewNode).nodeLoaded, @"Incorrect display node thread affinity - this method should not be called off the main thread after the ASDisplayNode's view or layer have been created")
|
||||
|
||||
@ -1100,14 +1100,7 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
||||
// measureWithSizeRange: on subnodes to assert.
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle placeholder layer creation in case the size of the node changed after the initial placeholder layer
|
||||
// was created
|
||||
if ([self _shouldHavePlaceholderLayer]) {
|
||||
[self _setupPlaceholderLayerIfNeeded];
|
||||
}
|
||||
_placeholderLayer.frame = bounds;
|
||||
|
||||
[self layout];
|
||||
[self layoutDidFinish];
|
||||
}
|
||||
@ -2762,12 +2755,7 @@ static const char *ASDisplayNodeDrawingPriorityKey = "ASDrawingPriority";
|
||||
|
||||
- (void)setEnvironmentState:(ASEnvironmentState)environmentState
|
||||
{
|
||||
ASEnvironmentTraitCollection oldTraitCollection = _environmentState.environmentTraitCollection;
|
||||
_environmentState = environmentState;
|
||||
|
||||
if (ASEnvironmentTraitCollectionIsEqualToASEnvironmentTraitCollection(oldTraitCollection, _environmentState.environmentTraitCollection) == NO) {
|
||||
[self asyncTraitCollectionDidChange];
|
||||
}
|
||||
}
|
||||
|
||||
- (ASDisplayNode *)parent
|
||||
@ -2797,10 +2785,7 @@ static const char *ASDisplayNodeDrawingPriorityKey = "ASDrawingPriority";
|
||||
|
||||
- (void)setEnvironmentTraitCollection:(ASEnvironmentTraitCollection)environmentTraitCollection
|
||||
{
|
||||
if (ASEnvironmentTraitCollectionIsEqualToASEnvironmentTraitCollection(environmentTraitCollection, _environmentState.environmentTraitCollection) == NO) {
|
||||
_environmentState.environmentTraitCollection = environmentTraitCollection;
|
||||
[self asyncTraitCollectionDidChange];
|
||||
}
|
||||
_environmentState.environmentTraitCollection = environmentTraitCollection;
|
||||
}
|
||||
|
||||
ASEnvironmentLayoutOptionsForwarding
|
||||
@ -2812,11 +2797,6 @@ ASEnvironmentLayoutExtensibilityForwarding
|
||||
return [ASTraitCollection traitCollectionWithASEnvironmentTraitCollection:self.environmentTraitCollection];
|
||||
}
|
||||
|
||||
- (void)asyncTraitCollectionDidChange
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#if TARGET_OS_TV
|
||||
#pragma mark - UIFocusEnvironment Protocol (tvOS)
|
||||
|
||||
|
||||
@ -22,6 +22,8 @@
|
||||
* This method replaces -collectionView:numberOfItemsInSection:
|
||||
*
|
||||
* @param pagerNode The sender.
|
||||
*
|
||||
*
|
||||
* @returns The total number of pages that can display in the pagerNode.
|
||||
*/
|
||||
- (NSInteger)numberOfPagesInPagerNode:(ASPagerNode *)pagerNode;
|
||||
@ -32,7 +34,9 @@
|
||||
* This method replaces -collectionView:nodeForItemAtIndexPath:
|
||||
*
|
||||
* @param pagerNode The sender.
|
||||
* @param index The index of the requested node.
|
||||
*
|
||||
* @param index The index of the requested node.
|
||||
*
|
||||
* @returns a node for display at this index. This will be called on the main thread and should
|
||||
* not implement reuse (it will be called once per row). Unlike UICollectionView's version,
|
||||
* this method is not called when the row is about to display.
|
||||
@ -44,7 +48,9 @@
|
||||
* This method takes precedence over pagerNode:nodeAtIndex: if implemented.
|
||||
*
|
||||
* @param pagerNode The sender.
|
||||
* @param index The index of the requested node.
|
||||
*
|
||||
* @param index The index of the requested node.
|
||||
*
|
||||
* @returns a block that creates the node for display at this index.
|
||||
* Must be thread-safe (can be called on the main thread or a background
|
||||
* queue) and should not implement reuse (it will be called once per row).
|
||||
@ -55,7 +61,9 @@
|
||||
* Provides the constrained size range for measuring the node at the index path.
|
||||
*
|
||||
* @param pagerNode The sender.
|
||||
*
|
||||
* @param indexPath The index path of the node.
|
||||
*
|
||||
* @returns A constrained size range for layout the node at this index path.
|
||||
*/
|
||||
- (ASSizeRange)pagerNode:(ASPagerNode *)pagerNode constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath;
|
||||
@ -68,46 +76,27 @@
|
||||
|
||||
@interface ASPagerNode : ASCollectionNode
|
||||
|
||||
/**
|
||||
* Configures a default horizontal, paging flow layout with 0 inter-item spacing.
|
||||
*/
|
||||
/// Configures a default horizontal, paging flow layout with 0 inter-item spacing.
|
||||
- (instancetype)init;
|
||||
|
||||
/**
|
||||
* Initializer with custom-configured flow layout properties.
|
||||
*/
|
||||
/// Initializer with custom-configured flow layout properties.
|
||||
- (instancetype)initWithCollectionViewLayout:(ASPagerFlowLayout *)flowLayout;
|
||||
|
||||
/**
|
||||
* Data Source is required, and uses a different protocol from ASCollectionNode.
|
||||
*/
|
||||
/// Data Source is required, and uses a different protocol from ASCollectionNode.
|
||||
- (void)setDataSource:(id <ASPagerDataSource>)dataSource;
|
||||
- (id <ASPagerDataSource>)dataSource;
|
||||
|
||||
/**
|
||||
* Delegate is optional, and uses the same protocol as ASCollectionNode.
|
||||
* This includes UIScrollViewDelegate as well as most methods from UICollectionViewDelegate, like willDisplay...
|
||||
*/
|
||||
// Delegate is optional, and uses the same protocol as ASCollectionNode.
|
||||
// This includes UIScrollViewDelegate as well as most methods from UICollectionViewDelegate, like willDisplay...
|
||||
@property (nonatomic, weak) id <ASPagerDelegate> delegate;
|
||||
|
||||
/**
|
||||
* The underlying ASCollectionView object.
|
||||
*/
|
||||
/// The underlying ASCollectionView object.
|
||||
@property (nonatomic, readonly) ASCollectionView *view;
|
||||
|
||||
/**
|
||||
* Returns the current page index
|
||||
*/
|
||||
/// Returns the current page index
|
||||
@property (nonatomic, assign, readonly) NSInteger currentPageIndex;
|
||||
|
||||
/**
|
||||
* Scroll the contents of the receiver to ensure that the page is visible
|
||||
*/
|
||||
/// Scroll the contents of the receiver to ensure that the page is visible
|
||||
- (void)scrollToPageAtIndex:(NSInteger)index animated:(BOOL)animated;
|
||||
|
||||
/**
|
||||
* Returns the node for the passed page index
|
||||
*/
|
||||
- (ASCellNode *)nodeForPageAtIndex:(NSInteger)index;
|
||||
|
||||
@end
|
||||
|
||||
@ -98,11 +98,6 @@
|
||||
[self.view scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionLeft animated:animated];
|
||||
}
|
||||
|
||||
- (ASCellNode *)nodeForPageAtIndex:(NSInteger)index
|
||||
{
|
||||
return [self.view nodeForItemAtIndexPath:[NSIndexPath indexPathForItem:index inSection:0]];
|
||||
}
|
||||
|
||||
#pragma mark - ASCollectionViewDataSource
|
||||
|
||||
- (ASCellNodeBlock)collectionView:(ASCollectionView *)collectionView nodeBlockForItemAtIndexPath:(NSIndexPath *)indexPath
|
||||
|
||||
@ -433,18 +433,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
- (BOOL)shouldBatchFetchForTableView:(ASTableView *)tableView;
|
||||
|
||||
/**
|
||||
* Provides the constrained size range for measuring the row at the index path.
|
||||
* Note: the widths in the returned size range are ignored!
|
||||
*
|
||||
* @param tableView The sender.
|
||||
*
|
||||
* @param indexPath The index path of the node.
|
||||
*
|
||||
* @returns A constrained size range for layout the node at this index path.
|
||||
*/
|
||||
- (ASSizeRange)tableView:(ASTableView *)tableView constrainedSizeForRowAtIndexPath:(NSIndexPath *)indexPath;
|
||||
|
||||
/**
|
||||
* Informs the delegate that the table view did remove the node which was previously
|
||||
* at the given index path from the view hierarchy.
|
||||
|
||||
@ -28,7 +28,6 @@
|
||||
|
||||
#import <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
static const ASSizeRange kInvalidSizeRange = {CGSizeZero, CGSizeZero};
|
||||
static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
|
||||
//#define LOG(...) NSLog(__VA_ARGS__)
|
||||
@ -145,7 +144,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
unsigned int asyncDelegateScrollViewWillEndDraggingWithVelocityTargetContentOffset:1;
|
||||
unsigned int asyncDelegateTableViewWillBeginBatchFetchWithContext:1;
|
||||
unsigned int asyncDelegateShouldBatchFetchForTableView:1;
|
||||
unsigned int asyncDelegateTableViewConstrainedSizeForRowAtIndexPath:1;
|
||||
} _asyncDelegateFlags;
|
||||
|
||||
struct {
|
||||
@ -166,7 +164,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
// Always set, whether ASCollectionView is created directly or via ASCollectionNode.
|
||||
@property (nonatomic, weak) ASTableNode *tableNode;
|
||||
|
||||
@property (nonatomic) BOOL test_enableSuperUpdateCallLogging;
|
||||
@end
|
||||
|
||||
@implementation ASTableView
|
||||
@ -338,8 +335,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
_asyncDelegateFlags.asyncDelegateShouldBatchFetchForTableView = [_asyncDelegate respondsToSelector:@selector(shouldBatchFetchForTableView:)];
|
||||
_asyncDelegateFlags.asyncDelegateScrollViewWillBeginDragging = [_asyncDelegate respondsToSelector:@selector(scrollViewWillBeginDragging:)];
|
||||
_asyncDelegateFlags.asyncDelegateScrollViewDidEndDragging = [_asyncDelegate respondsToSelector:@selector(scrollViewDidEndDragging:willDecelerate:)];
|
||||
_asyncDelegateFlags.asyncDelegateTableViewConstrainedSizeForRowAtIndexPath = [_asyncDelegate respondsToSelector:@selector(tableView:constrainedSizeForRowAtIndexPath:)];
|
||||
|
||||
}
|
||||
|
||||
super.delegate = (id<UITableViewDelegate>)_proxyDelegate;
|
||||
@ -479,21 +474,18 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
if (sections.count == 0) { return; }
|
||||
[_dataController insertSections:sections withAnimationOptions:animation];
|
||||
}
|
||||
|
||||
- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
if (sections.count == 0) { return; }
|
||||
[_dataController deleteSections:sections withAnimationOptions:animation];
|
||||
}
|
||||
|
||||
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
if (sections.count == 0) { return; }
|
||||
[_dataController reloadSections:sections withAnimationOptions:animation];
|
||||
}
|
||||
|
||||
@ -506,21 +498,18 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
if (indexPaths.count == 0) { return; }
|
||||
[_dataController insertRowsAtIndexPaths:indexPaths withAnimationOptions:animation];
|
||||
}
|
||||
|
||||
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
if (indexPaths.count == 0) { return; }
|
||||
[_dataController deleteRowsAtIndexPaths:indexPaths withAnimationOptions:animation];
|
||||
}
|
||||
|
||||
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
|
||||
{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
if (indexPaths.count == 0) { return; }
|
||||
[_dataController reloadRowsAtIndexPaths:indexPaths withAnimationOptions:animation];
|
||||
}
|
||||
|
||||
@ -1004,9 +993,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
|
||||
BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone;
|
||||
ASPerformBlockWithoutAnimation(preventAnimation, ^{
|
||||
if (self.test_enableSuperUpdateCallLogging) {
|
||||
NSLog(@"-[super insertRowsAtIndexPaths]: %@", indexPaths);
|
||||
}
|
||||
[super insertRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOptions];
|
||||
[self _scheduleCheckForBatchFetchingForNumberOfChanges:indexPaths.count];
|
||||
});
|
||||
@ -1027,9 +1013,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
|
||||
BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone;
|
||||
ASPerformBlockWithoutAnimation(preventAnimation, ^{
|
||||
if (self.test_enableSuperUpdateCallLogging) {
|
||||
NSLog(@"-[super deleteRowsAtIndexPaths]: %@", indexPaths);
|
||||
}
|
||||
[super deleteRowsAtIndexPaths:indexPaths withRowAnimation:(UITableViewRowAnimation)animationOptions];
|
||||
[self _scheduleCheckForBatchFetchingForNumberOfChanges:indexPaths.count];
|
||||
});
|
||||
@ -1051,9 +1034,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
|
||||
BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone;
|
||||
ASPerformBlockWithoutAnimation(preventAnimation, ^{
|
||||
if (self.test_enableSuperUpdateCallLogging) {
|
||||
NSLog(@"-[super insertSections]: %@", indexSet);
|
||||
}
|
||||
[super insertSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOptions];
|
||||
[self _scheduleCheckForBatchFetchingForNumberOfChanges:indexSet.count];
|
||||
});
|
||||
@ -1070,9 +1050,6 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
|
||||
BOOL preventAnimation = animationOptions == UITableViewRowAnimationNone;
|
||||
ASPerformBlockWithoutAnimation(preventAnimation, ^{
|
||||
if (self.test_enableSuperUpdateCallLogging) {
|
||||
NSLog(@"-[super deleteSections]: %@", indexSet);
|
||||
}
|
||||
[super deleteSections:indexSet withRowAnimation:(UITableViewRowAnimation)animationOptions];
|
||||
[self _scheduleCheckForBatchFetchingForNumberOfChanges:indexSet.count];
|
||||
});
|
||||
@ -1111,17 +1088,8 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
||||
|
||||
- (ASSizeRange)dataController:(ASDataController *)dataController constrainedSizeForNodeAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
ASSizeRange constrainedSize = kInvalidSizeRange;
|
||||
if (_asyncDelegateFlags.asyncDelegateTableViewConstrainedSizeForRowAtIndexPath) {
|
||||
ASSizeRange delegateConstrainedSize = [_asyncDelegate tableView:self constrainedSizeForRowAtIndexPath:indexPath];
|
||||
// ignore widths in the returned size range (for TableView)
|
||||
constrainedSize = ASSizeRangeMake(CGSizeMake(_nodesConstrainedWidth, delegateConstrainedSize.min.height),
|
||||
CGSizeMake(_nodesConstrainedWidth, delegateConstrainedSize.max.height));
|
||||
} else {
|
||||
constrainedSize = ASSizeRangeMake(CGSizeMake(_nodesConstrainedWidth, 0),
|
||||
CGSizeMake(_nodesConstrainedWidth, FLT_MAX));
|
||||
}
|
||||
return constrainedSize;
|
||||
return ASSizeRangeMake(CGSizeMake(_nodesConstrainedWidth, 0),
|
||||
CGSizeMake(_nodesConstrainedWidth, FLT_MAX));
|
||||
}
|
||||
|
||||
- (NSUInteger)dataController:(ASDataController *)dataController rowsInSection:(NSUInteger)section
|
||||
|
||||
@ -34,7 +34,4 @@
|
||||
*/
|
||||
- (instancetype)_initWithFrame:(CGRect)frame style:(UITableViewStyle)style dataControllerClass:(Class)dataControllerClass ownedByNode:(BOOL)ownedByNode;
|
||||
|
||||
/// Set YES and we'll log every time we call [super insertRows…] etc
|
||||
@property (nonatomic) BOOL test_enableSuperUpdateCallLogging;
|
||||
|
||||
@end
|
||||
|
||||
@ -366,36 +366,32 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
||||
|
||||
- (void)setAttributedText:(NSAttributedString *)attributedText
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> l(_textLock);
|
||||
|
||||
if (attributedText == nil) {
|
||||
attributedText = [[NSAttributedString alloc] initWithString:@"" attributes:nil];
|
||||
}
|
||||
|
||||
// Don't hold textLock for too long.
|
||||
{
|
||||
std::lock_guard<std::recursive_mutex> l(_textLock);
|
||||
if (ASObjectIsEqual(attributedText, _attributedText)) {
|
||||
return;
|
||||
}
|
||||
|
||||
_attributedText = ASCleanseAttributedStringOfCoreTextAttributes(attributedText);
|
||||
|
||||
// Sync the truncation string with attributes from the updated _attributedString
|
||||
// Without this, the size calculation of the text with truncation applied will
|
||||
// not take into account the attributes of attributedText in the last line
|
||||
[self _updateComposedTruncationText];
|
||||
|
||||
// We need an entirely new renderer
|
||||
[self _invalidateRenderer];
|
||||
if (ASObjectIsEqual(attributedText, _attributedText)) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSUInteger length = attributedText.length;
|
||||
if (length > 0) {
|
||||
|
||||
_attributedText = ASCleanseAttributedStringOfCoreTextAttributes(attributedText);
|
||||
|
||||
if (_attributedText.length > 0) {
|
||||
CGFloat screenScale = ASScreenScale();
|
||||
self.ascender = round([[attributedText attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL] ascender] * screenScale)/screenScale;
|
||||
self.descender = round([[attributedText attribute:NSFontAttributeName atIndex:length - 1 effectiveRange:NULL] descender] * screenScale)/screenScale;
|
||||
self.ascender = round([[_attributedText attribute:NSFontAttributeName atIndex:0 effectiveRange:NULL] ascender] * screenScale)/screenScale;
|
||||
self.descender = round([[_attributedText attribute:NSFontAttributeName atIndex:_attributedText.length - 1 effectiveRange:NULL] descender] * screenScale)/screenScale;
|
||||
}
|
||||
|
||||
// Sync the truncation string with attributes from the updated _attributedString
|
||||
// Without this, the size calculation of the text with truncation applied will
|
||||
// not take into account the attributes of attributedText in the last line
|
||||
[self _updateComposedTruncationText];
|
||||
|
||||
// We need an entirely new renderer
|
||||
[self _invalidateRenderer];
|
||||
|
||||
// Tell the display node superclasses that the cached layout is incorrect now
|
||||
[self invalidateCalculatedLayout];
|
||||
|
||||
@ -403,8 +399,8 @@ static NSArray *DefaultLinkAttributeNames = @[ NSLinkAttributeName ];
|
||||
|
||||
|
||||
// Accessiblity
|
||||
self.accessibilityLabel = attributedText.string;
|
||||
self.isAccessibilityElement = (length != 0); // We're an accessibility element by default if there is a string.
|
||||
self.accessibilityLabel = _attributedText.string;
|
||||
self.isAccessibilityElement = (_attributedText.length != 0); // We're an accessibility element by default if there is a string.
|
||||
}
|
||||
|
||||
#pragma mark - Text Layout
|
||||
|
||||
@ -164,10 +164,6 @@ static NSString * const kStatus = @"status";
|
||||
|
||||
- (void)addPlayerItemObservers:(AVPlayerItem *)playerItem
|
||||
{
|
||||
if (playerItem == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
[playerItem addObserver:self forKeyPath:kStatus options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew context:ASVideoNodeContext];
|
||||
[playerItem addObserver:self forKeyPath:kPlaybackLikelyToKeepUpKey options:NSKeyValueObservingOptionNew context:ASVideoNodeContext];
|
||||
[playerItem addObserver:self forKeyPath:kplaybackBufferEmpty options:NSKeyValueObservingOptionNew context:ASVideoNodeContext];
|
||||
@ -645,9 +641,7 @@ static NSString * const kStatus = @"status";
|
||||
|
||||
_currentPlayerItem = currentItem;
|
||||
|
||||
if (currentItem != nil) {
|
||||
[self addPlayerItemObservers:currentItem];
|
||||
}
|
||||
[self addPlayerItemObservers:currentItem];
|
||||
}
|
||||
|
||||
- (ASDisplayNode *)playerNode
|
||||
|
||||
@ -49,7 +49,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@property (nonatomic, assign, readwrite) BOOL muted;
|
||||
@property (nonatomic, assign, readonly) ASVideoNodePlayerState playerState;
|
||||
@property (nonatomic, assign, readwrite) BOOL shouldAggressivelyRecoverFromStall;
|
||||
@property (nullable, atomic, strong, readwrite) NSURL *placeholderImageURL;
|
||||
|
||||
//! Defaults to 100
|
||||
@property (nonatomic, assign) int32_t periodicTimeObserverTimescale;
|
||||
|
||||
@ -76,9 +76,6 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
|
||||
@end
|
||||
|
||||
@implementation ASVideoPlayerNode
|
||||
|
||||
@dynamic placeholderImageURL;
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if (!(self = [super init])) {
|
||||
@ -774,16 +771,6 @@ static void *ASVideoPlayerNodeContext = &ASVideoPlayerNodeContext;
|
||||
return _videoNode.shouldAggressivelyRecoverFromStall;
|
||||
}
|
||||
|
||||
- (void) setPlaceholderImageURL:(NSURL *)placeholderImageURL
|
||||
{
|
||||
_videoNode.URL = placeholderImageURL;
|
||||
}
|
||||
|
||||
- (NSURL*) placeholderImageURL
|
||||
{
|
||||
return _videoNode.URL;
|
||||
}
|
||||
|
||||
- (void)setShouldAggressivelyRecoverFromStall:(BOOL)shouldAggressivelyRecoverFromStall
|
||||
{
|
||||
if (_shouldAggressivelyRecoverFromStall == shouldAggressivelyRecoverFromStall) {
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
#import "ASInternalHelpers.h"
|
||||
#import "_ASHierarchyChangeSet.h"
|
||||
#import "ASAssert.h"
|
||||
#import "NSIndexSet+ASHelpers.h"
|
||||
|
||||
#import "ASDataController+Subclasses.h"
|
||||
|
||||
@ -48,9 +47,6 @@
|
||||
|
||||
[super beginUpdates];
|
||||
|
||||
NSAssert([_changeSet itemChangesOfType:_ASHierarchyChangeTypeReload].count == 0, @"Expected reload item changes to have been converted into insert/deletes.");
|
||||
NSAssert([_changeSet sectionChangesOfType:_ASHierarchyChangeTypeReload].count == 0, @"Expected reload section changes to have been converted into insert/deletes.");
|
||||
|
||||
for (_ASHierarchyItemChange *change in [_changeSet itemChangesOfType:_ASHierarchyChangeTypeDelete]) {
|
||||
[super deleteRowsAtIndexPaths:change.indexPaths withAnimationOptions:change.animationOptions];
|
||||
}
|
||||
@ -58,7 +54,17 @@
|
||||
for (_ASHierarchySectionChange *change in [_changeSet sectionChangesOfType:_ASHierarchyChangeTypeDelete]) {
|
||||
[super deleteSections:change.indexSet withAnimationOptions:change.animationOptions];
|
||||
}
|
||||
|
||||
|
||||
// TODO: Shouldn't reloads be processed before deletes, since deletes affect
|
||||
// the index space and reloads don't?
|
||||
for (_ASHierarchySectionChange *change in [_changeSet sectionChangesOfType:_ASHierarchyChangeTypeReload]) {
|
||||
[super reloadSections:change.indexSet withAnimationOptions:change.animationOptions];
|
||||
}
|
||||
|
||||
for (_ASHierarchyItemChange *change in [_changeSet itemChangesOfType:_ASHierarchyChangeTypeReload]) {
|
||||
[super reloadRowsAtIndexPaths:change.indexPaths withAnimationOptions:change.animationOptions];
|
||||
}
|
||||
|
||||
for (_ASHierarchySectionChange *change in [_changeSet sectionChangesOfType:_ASHierarchyChangeTypeInsert]) {
|
||||
[super insertSections:change.indexSet withAnimationOptions:change.animationOptions];
|
||||
}
|
||||
@ -109,10 +115,7 @@
|
||||
if ([self batchUpdating]) {
|
||||
[_changeSet reloadSections:sections animationOptions:animationOptions];
|
||||
} else {
|
||||
[self beginUpdates];
|
||||
[super deleteSections:sections withAnimationOptions:animationOptions];
|
||||
[super insertSections:sections withAnimationOptions:animationOptions];
|
||||
[self endUpdates];
|
||||
[super reloadSections:sections withAnimationOptions:animationOptions];
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,10 +158,7 @@
|
||||
if ([self batchUpdating]) {
|
||||
[_changeSet reloadItems:indexPaths animationOptions:animationOptions];
|
||||
} else {
|
||||
[self beginUpdates];
|
||||
[super deleteRowsAtIndexPaths:indexPaths withAnimationOptions:animationOptions];
|
||||
[super insertRowsAtIndexPaths:indexPaths withAnimationOptions:animationOptions];
|
||||
[self endUpdates];
|
||||
[super reloadRowsAtIndexPaths:indexPaths withAnimationOptions:animationOptions];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -115,6 +115,30 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)prepareForReloadSections:(NSIndexSet *)sections
|
||||
{
|
||||
for (NSString *kind in [self supplementaryKinds]) {
|
||||
NSMutableArray<ASIndexedNodeContext *> *contexts = [NSMutableArray array];
|
||||
[self _populateSupplementaryNodesOfKind:kind withSections:sections mutableContexts:contexts];
|
||||
_pendingContexts[kind] = contexts;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)willReloadSections:(NSIndexSet *)sections
|
||||
{
|
||||
NSArray *keys = _pendingContexts.allKeys;
|
||||
for (NSString *kind in keys) {
|
||||
NSMutableArray<ASIndexedNodeContext *> *contexts = _pendingContexts[kind];
|
||||
NSArray *indexPaths = ASIndexPathsForMultidimensionalArrayAtIndexSet([self editingNodesOfKind:kind], sections);
|
||||
[self deleteNodesOfKind:kind atIndexPaths:indexPaths completion:nil];
|
||||
// reinsert the elements
|
||||
[self batchLayoutNodesFromContexts:contexts ofKind:kind completion:^(NSArray<ASCellNode *> *nodes, NSArray<NSIndexPath *> *indexPaths) {
|
||||
[self insertNodes:nodes ofKind:kind atIndexPaths:indexPaths completion:nil];
|
||||
}];
|
||||
[_pendingContexts removeObjectForKey:kind];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)willMoveSection:(NSInteger)section toSection:(NSInteger)newSection
|
||||
{
|
||||
for (NSString *kind in [self supplementaryKinds]) {
|
||||
@ -163,6 +187,30 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)prepareForReloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
|
||||
{
|
||||
for (NSString *kind in [self supplementaryKinds]) {
|
||||
NSMutableArray<ASIndexedNodeContext *> *contexts = [NSMutableArray array];
|
||||
[self _populateSupplementaryNodesOfKind:kind atIndexPaths:indexPaths mutableContexts:contexts];
|
||||
_pendingContexts[kind] = contexts;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)willReloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
|
||||
{
|
||||
NSArray *keys = _pendingContexts.allKeys;
|
||||
for (NSString *kind in keys) {
|
||||
NSMutableArray<ASIndexedNodeContext *> *contexts = _pendingContexts[kind];
|
||||
|
||||
[self deleteNodesOfKind:kind atIndexPaths:indexPaths completion:nil];
|
||||
// reinsert the elements
|
||||
[self batchLayoutNodesFromContexts:contexts ofKind:kind completion:^(NSArray<ASCellNode *> *nodes, NSArray<NSIndexPath *> *indexPaths) {
|
||||
[self insertNodes:nodes ofKind:kind atIndexPaths:indexPaths completion:nil];
|
||||
}];
|
||||
[_pendingContexts removeObjectForKey:kind];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_populateSupplementaryNodesOfKind:(NSString *)kind withMutableContexts:(NSMutableArray<ASIndexedNodeContext *> *)contexts
|
||||
{
|
||||
id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
||||
|
||||
@ -128,6 +128,28 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCellNode *> *nodes, NS
|
||||
*/
|
||||
- (void)willDeleteSections:(NSIndexSet *)sections;
|
||||
|
||||
/**
|
||||
* Notifies the subclass to perform any work needed before the given sections will be reloaded.
|
||||
*
|
||||
* @discussion This method will be performed before the data controller enters its editing queue, usually on the main
|
||||
* thread. The data source is locked at this point and accessing it is safe. Use this method to set up any nodes or
|
||||
* data stores before entering into editing the backing store on a background thread.
|
||||
*
|
||||
* @param sections Indices of sections to be reloaded
|
||||
*/
|
||||
- (void)prepareForReloadSections:(NSIndexSet *)sections;
|
||||
|
||||
/**
|
||||
* Notifies the subclass that the data controller will reload the sections in the given index set
|
||||
*
|
||||
* @discussion This method will be performed on the data controller's editing background queue before the parent's
|
||||
* concrete implementation. This is a great place to perform any additional transformations like supplementary views
|
||||
* or header/footer nodes.
|
||||
*
|
||||
* @param sections Indices of sections to be reloaded
|
||||
*/
|
||||
- (void)willReloadSections:(NSIndexSet *)sections;
|
||||
|
||||
/**
|
||||
* Notifies the subclass that the data controller will move a section to a new position
|
||||
*
|
||||
@ -184,4 +206,26 @@ typedef void (^ASDataControllerCompletionBlock)(NSArray<ASCellNode *> *nodes, NS
|
||||
*/
|
||||
- (void)willDeleteRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
|
||||
|
||||
/**
|
||||
* Notifies the subclass to perform any work needed before the given rows will be reloaded.
|
||||
*
|
||||
* @discussion This method will be performed before the data controller enters its editing queue, usually on the main
|
||||
* thread. The data source is locked at this point and accessing it is safe. Use this method to set up any nodes or
|
||||
* data stores before entering into editing the backing store on a background thread.
|
||||
*
|
||||
* @param indexPaths Index paths for the rows to be reloaded.
|
||||
*/
|
||||
- (void)prepareForReloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
|
||||
|
||||
/**
|
||||
* Notifies the subclass that the data controller will reload the rows at the given index paths.
|
||||
*
|
||||
* @discussion This method will be performed on the data controller's editing background queue before the parent's
|
||||
* concrete implementation. This is a great place to perform any additional transformations like supplementary views
|
||||
* or header/footer nodes.
|
||||
*
|
||||
* @param indexPaths Index paths for the rows to be reloaded.
|
||||
*/
|
||||
- (void)willReloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths;
|
||||
|
||||
@end
|
||||
|
||||
@ -65,7 +65,6 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
if (!(self = [super init])) {
|
||||
return nil;
|
||||
}
|
||||
ASDisplayNodeAssert(![self isMemberOfClass:[ASDataController class]], @"ASDataController is an abstract class and should not be instantiated. Instantiate a subclass instead.");
|
||||
|
||||
_completedNodes = [NSMutableDictionary dictionary];
|
||||
_editingNodes = [NSMutableDictionary dictionary];
|
||||
@ -143,9 +142,8 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
*/
|
||||
- (void)_layoutNode:(ASCellNode *)node withConstrainedSize:(ASSizeRange)constrainedSize
|
||||
{
|
||||
CGRect frame = CGRectZero;
|
||||
frame.size = [node measureWithSizeRange:constrainedSize].size;
|
||||
node.frame = frame;
|
||||
CGSize size = [node measureWithSizeRange:constrainedSize].size;
|
||||
node.frame = { .size = size };
|
||||
}
|
||||
|
||||
/**
|
||||
@ -663,7 +661,29 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
|
||||
- (void)reloadSections:(NSIndexSet *)sections withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
|
||||
{
|
||||
ASDisplayNodeAssert(NO, @"ASDataController does not support %@. Call this on ASChangeSetDataController the reload will be broken into delete & insert.", NSStringFromSelector(_cmd));
|
||||
[self performEditCommandWithBlock:^{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
LOG(@"Edit Command - reloadSections: %@", sections);
|
||||
|
||||
[_editingTransactionQueue waitUntilAllOperationsAreFinished];
|
||||
|
||||
NSArray<ASIndexedNodeContext *> *contexts= [self _populateFromDataSourceWithSectionIndexSet:sections];
|
||||
|
||||
[self prepareForReloadSections:sections];
|
||||
|
||||
[_editingTransactionQueue addOperationWithBlock:^{
|
||||
[self willReloadSections:sections];
|
||||
|
||||
NSArray *indexPaths = ASIndexPathsForMultidimensionalArrayAtIndexSet(_editingNodes[ASDataControllerRowNodeKind], sections);
|
||||
|
||||
LOG(@"Edit Transaction - reloadSections: updatedIndexPaths: %@, indexPaths: %@, _editingNodes: %@", updatedIndexPaths, indexPaths, ASIndexPathsForTwoDimensionalArray(_editingNodes[ASDataControllerRowNodeKind]));
|
||||
|
||||
[self _deleteNodesAtIndexPaths:indexPaths withAnimationOptions:animationOptions];
|
||||
|
||||
// reinsert the elements
|
||||
[self _batchLayoutNodesFromContexts:contexts withAnimationOptions:animationOptions];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)moveSection:(NSInteger)section toSection:(NSInteger)newSection withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
|
||||
@ -726,6 +746,16 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
// Optional template hook for subclasses (See ASDataController+Subclasses.h)
|
||||
}
|
||||
|
||||
- (void)prepareForReloadSections:(NSIndexSet *)sections
|
||||
{
|
||||
// Optional template hook for subclasses (See ASDataController+Subclasses.h)
|
||||
}
|
||||
|
||||
- (void)willReloadSections:(NSIndexSet *)sections
|
||||
{
|
||||
// Optional template hook for subclasses (See ASDataController+Subclasses.h)
|
||||
}
|
||||
|
||||
- (void)willMoveSection:(NSInteger)section toSection:(NSInteger)newSection
|
||||
{
|
||||
// Optional template hook for subclasses (See ASDataController+Subclasses.h)
|
||||
@ -751,6 +781,16 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
// Optional template hook for subclasses (See ASDataController+Subclasses.h)
|
||||
}
|
||||
|
||||
- (void)prepareForReloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
|
||||
{
|
||||
// Optional template hook for subclasses (See ASDataController+Subclasses.h)
|
||||
}
|
||||
|
||||
- (void)willReloadRowsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths
|
||||
{
|
||||
// Optional template hook for subclasses (See ASDataController+Subclasses.h)
|
||||
}
|
||||
|
||||
#pragma mark - Row Editing (External API)
|
||||
|
||||
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
|
||||
@ -813,7 +853,40 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
|
||||
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withAnimationOptions:(ASDataControllerAnimationOptions)animationOptions
|
||||
{
|
||||
ASDisplayNodeAssert(NO, @"ASDataController does not support %@. Call this on ASChangeSetDataController and the reload will be broken into delete & insert.", NSStringFromSelector(_cmd));
|
||||
[self performEditCommandWithBlock:^{
|
||||
ASDisplayNodeAssertMainThread();
|
||||
LOG(@"Edit Command - reloadRows: %@", indexPaths);
|
||||
|
||||
[_editingTransactionQueue waitUntilAllOperationsAreFinished];
|
||||
|
||||
NSMutableArray<ASIndexedNodeContext *> *contexts = [[NSMutableArray alloc] initWithCapacity:indexPaths.count];
|
||||
|
||||
// Sort indexPath to avoid messing up the index when deleting
|
||||
// FIXME: Shouldn't deletes be sorted in descending order?
|
||||
NSArray *sortedIndexPaths = [indexPaths sortedArrayUsingSelector:@selector(compare:)];
|
||||
|
||||
id<ASEnvironment> environment = [self.environmentDelegate dataControllerEnvironment];
|
||||
ASEnvironmentTraitCollection environmentTraitCollection = environment.environmentTraitCollection;
|
||||
|
||||
for (NSIndexPath *indexPath in sortedIndexPaths) {
|
||||
ASCellNodeBlock nodeBlock = [_dataSource dataController:self nodeBlockAtIndexPath:indexPath];
|
||||
ASSizeRange constrainedSize = [self constrainedSizeForNodeOfKind:ASDataControllerRowNodeKind atIndexPath:indexPath];
|
||||
[contexts addObject:[[ASIndexedNodeContext alloc] initWithNodeBlock:nodeBlock
|
||||
indexPath:indexPath
|
||||
constrainedSize:constrainedSize
|
||||
environmentTraitCollection:environmentTraitCollection]];
|
||||
}
|
||||
|
||||
[self prepareForReloadRowsAtIndexPaths:indexPaths];
|
||||
|
||||
[_editingTransactionQueue addOperationWithBlock:^{
|
||||
[self willReloadRowsAtIndexPaths:indexPaths];
|
||||
|
||||
LOG(@"Edit Transaction - reloadRows: %@", indexPaths);
|
||||
[self _deleteNodesAtIndexPaths:sortedIndexPaths withAnimationOptions:animationOptions];
|
||||
[self _batchLayoutNodesFromContexts:contexts withAnimationOptions:animationOptions];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)relayoutAllNodes
|
||||
@ -850,9 +923,8 @@ static void *kASSizingQueueContext = &kASSizingQueueContext;
|
||||
for (ASCellNode *node in section) {
|
||||
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowIndex inSection:sectionIndex];
|
||||
ASSizeRange constrainedSize = [self constrainedSizeForNodeOfKind:kind atIndexPath:indexPath];
|
||||
CGRect frame = CGRectZero;
|
||||
frame.size = [node measureWithSizeRange:constrainedSize].size;
|
||||
node.frame = frame;
|
||||
CGSize size = [node measureWithSizeRange:constrainedSize].size;
|
||||
node.frame = { .size = size };
|
||||
rowIndex += 1;
|
||||
}
|
||||
sectionIndex += 1;
|
||||
|
||||
@ -118,15 +118,6 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)conformsToProtocol:(Protocol *)aProtocol
|
||||
{
|
||||
if (_target) {
|
||||
return [_target conformsToProtocol:aProtocol];
|
||||
} else {
|
||||
return [super conformsToProtocol:aProtocol];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)respondsToSelector:(SEL)aSelector
|
||||
{
|
||||
if ([self interceptsSelector:aSelector]) {
|
||||
|
||||
@ -157,10 +157,6 @@ ASDISPLAYNODE_EXTERN_C_END
|
||||
ASDN::MutexLocker l(lock);\
|
||||
ASEnvironmentTraitCollection oldTraits = self.environmentState.environmentTraitCollection;\
|
||||
[super setEnvironmentState:environmentState];\
|
||||
\
|
||||
/* Extra Trait Collection Handling */\
|
||||
/* If the node is not loaded yet don't do anything as otherwise the access of the view will trigger a load*/\
|
||||
if (!self.isNodeLoaded) { return; } \
|
||||
ASEnvironmentTraitCollection currentTraits = environmentState.environmentTraitCollection;\
|
||||
if (ASEnvironmentTraitCollectionIsEqualToASEnvironmentTraitCollection(currentTraits, oldTraits) == NO) {\
|
||||
/* Must dispatch to main for self.view && [self.view.dataController completedNodes]*/ \
|
||||
|
||||
@ -92,12 +92,12 @@
|
||||
currPath.row++;
|
||||
|
||||
// Once we reach the end of the section, advance to the next one. Keep advancing if the next section is zero-sized.
|
||||
while (currPath.row >= [(NSArray *)completedNodes[currPath.section] count] && currPath.section < endPath.section) {
|
||||
while (currPath.row >= [(NSArray *)completedNodes[currPath.section] count] && currPath.section < completedNodes.count - 1) {
|
||||
currPath.row = 0;
|
||||
currPath.section++;
|
||||
ASDisplayNodeAssert(currPath.section <= endPath.section, @"currPath should never reach a further section than endPath");
|
||||
}
|
||||
}
|
||||
ASDisplayNodeAssert(currPath.section <= endPath.section, @"currPath should never reach a further section than endPath");
|
||||
|
||||
[indexPathSet addObject:[NSIndexPath indexPathWithASIndexPath:endPath]];
|
||||
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
//
|
||||
// NSIndexSet+ASHelpers.h
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Adlai Holler on 6/23/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface NSIndexSet (ASHelpers)
|
||||
|
||||
- (NSIndexSet *)as_indexesByMapping:(NSUInteger (^)(NSUInteger idx))block;
|
||||
|
||||
- (NSIndexSet *)as_intersectionWithIndexes:(NSIndexSet *)indexes;
|
||||
|
||||
/// Returns all the item indexes from the given index paths that are in the given section.
|
||||
+ (NSIndexSet *)as_indexSetFromIndexPaths:(NSArray<NSIndexPath *> *)indexPaths inSection:(NSUInteger)section;
|
||||
|
||||
/// If you've got an old index, and you insert items using this index set, this returns the change to get to the new index.
|
||||
- (NSUInteger)as_indexChangeByInsertingItemsBelowIndex:(NSUInteger)index;
|
||||
|
||||
- (NSString *)as_smallDescription;
|
||||
|
||||
@end
|
||||
@ -1,76 +0,0 @@
|
||||
//
|
||||
// NSIndexSet+ASHelpers.m
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Adlai Holler on 6/23/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#import "NSIndexSet+ASHelpers.h"
|
||||
|
||||
@implementation NSIndexSet (ASHelpers)
|
||||
|
||||
- (NSIndexSet *)as_indexesByMapping:(NSUInteger (^)(NSUInteger))block
|
||||
{
|
||||
NSMutableIndexSet *result = [NSMutableIndexSet indexSet];
|
||||
[self enumerateIndexesUsingBlock:^(NSUInteger idx, __unused BOOL * _Nonnull stop) {
|
||||
NSUInteger newIndex = block(idx);
|
||||
if (newIndex != NSNotFound) {
|
||||
[result addIndex:newIndex];
|
||||
}
|
||||
}];
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSIndexSet *)as_intersectionWithIndexes:(NSIndexSet *)indexes
|
||||
{
|
||||
NSMutableIndexSet *result = [NSMutableIndexSet indexSet];
|
||||
[self enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
||||
[indexes enumerateRangesInRange:range options:kNilOptions usingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
||||
[result addIndexesInRange:range];
|
||||
}];
|
||||
}];
|
||||
return result;
|
||||
}
|
||||
|
||||
+ (NSIndexSet *)as_indexSetFromIndexPaths:(NSArray<NSIndexPath *> *)indexPaths inSection:(NSUInteger)section
|
||||
{
|
||||
NSMutableIndexSet *result = [NSMutableIndexSet indexSet];
|
||||
for (NSIndexPath *indexPath in indexPaths) {
|
||||
if (indexPath.section == section) {
|
||||
[result addIndex:indexPath.item];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSUInteger)as_indexChangeByInsertingItemsBelowIndex:(NSUInteger)index
|
||||
{
|
||||
__block NSUInteger newIndex = index;
|
||||
[self enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
if (idx <= newIndex) {
|
||||
newIndex += 1;
|
||||
} else {
|
||||
*stop = YES;
|
||||
}
|
||||
}];
|
||||
return newIndex - index;
|
||||
}
|
||||
|
||||
- (NSString *)as_smallDescription
|
||||
{
|
||||
NSMutableString *result = [NSMutableString stringWithString:@"{ "];
|
||||
[self enumerateRangesUsingBlock:^(NSRange range, BOOL * _Nonnull stop) {
|
||||
if (range.length == 1) {
|
||||
[result appendFormat:@"%lu ", (unsigned long)range.location];
|
||||
} else {
|
||||
[result appendFormat:@"%lu-%lu ", (unsigned long)range.location, (unsigned long)NSMaxRange(range)];
|
||||
}
|
||||
}];
|
||||
[result appendString:@"}"];
|
||||
return result;
|
||||
}
|
||||
|
||||
@end
|
||||
@ -13,8 +13,6 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <AsyncDisplayKit/ASInternalHelpers.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef NSUInteger ASDataControllerAnimationOptions;
|
||||
|
||||
typedef NS_ENUM(NSInteger, _ASHierarchyChangeType) {
|
||||
@ -23,8 +21,6 @@ typedef NS_ENUM(NSInteger, _ASHierarchyChangeType) {
|
||||
_ASHierarchyChangeTypeInsert
|
||||
};
|
||||
|
||||
NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType);
|
||||
|
||||
@interface _ASHierarchySectionChange : NSObject
|
||||
|
||||
// FIXME: Generalize this to `changeMetadata` dict?
|
||||
@ -38,11 +34,11 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType);
|
||||
@property (nonatomic, readonly) ASDataControllerAnimationOptions animationOptions;
|
||||
|
||||
/// Index paths are sorted descending for changeType .Delete, ascending otherwise
|
||||
@property (nonatomic, strong, readonly) NSArray<NSIndexPath *> *indexPaths;
|
||||
@property (nonatomic, strong, readonly) NSArray *indexPaths;
|
||||
|
||||
@property (nonatomic, readonly) _ASHierarchyChangeType changeType;
|
||||
|
||||
+ (NSDictionary *)sectionToIndexSetMapFromChanges:(NSArray<_ASHierarchyItemChange *> *)changes ofType:(_ASHierarchyChangeType)changeType;
|
||||
+ (NSDictionary *)sectionToIndexSetMapFromChanges:(NSArray *)changes ofType:(_ASHierarchyChangeType)changeType;
|
||||
@end
|
||||
|
||||
@interface _ASHierarchyChangeSet : NSObject
|
||||
@ -51,6 +47,8 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType);
|
||||
@property (nonatomic, strong, readonly) NSIndexSet *deletedSections;
|
||||
/// @precondition The change set must be completed.
|
||||
@property (nonatomic, strong, readonly) NSIndexSet *insertedSections;
|
||||
/// @precondition The change set must be completed.
|
||||
@property (nonatomic, strong, readonly) NSIndexSet *reloadedSections;
|
||||
|
||||
/**
|
||||
Get the section index after the update for the given section before the update.
|
||||
@ -58,12 +56,11 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType);
|
||||
@precondition The change set must be completed.
|
||||
@returns The new section index, or NSNotFound if the given section was deleted.
|
||||
*/
|
||||
- (NSUInteger)newSectionForOldSection:(NSUInteger)oldSection;
|
||||
- (NSInteger)newSectionForOldSection:(NSInteger)oldSection;
|
||||
|
||||
@property (nonatomic, readonly) BOOL completed;
|
||||
|
||||
/// Call this once the change set has been constructed to prevent future modifications to the changeset. Calling this more than once is a programmer error.
|
||||
/// NOTE: Calling this method will cause the changeset to convert all reloads into delete/insert pairs.
|
||||
- (void)markCompleted;
|
||||
|
||||
/**
|
||||
@ -80,18 +77,13 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType);
|
||||
- Inserted sections, ascending order
|
||||
- Inserted items, ascending order
|
||||
*/
|
||||
- (nullable NSArray <_ASHierarchySectionChange *> *)sectionChangesOfType:(_ASHierarchyChangeType)changeType;
|
||||
- (nullable NSArray <_ASHierarchyItemChange *> *)itemChangesOfType:(_ASHierarchyChangeType)changeType;
|
||||
|
||||
/// Returns all item indexes affected by changes of the given type in the given section.
|
||||
- (NSIndexSet *)indexesForItemChangesOfType:(_ASHierarchyChangeType)changeType inSection:(NSUInteger)section;
|
||||
- (NSArray /*<_ASHierarchySectionChange *>*/ *)sectionChangesOfType:(_ASHierarchyChangeType)changeType;
|
||||
- (NSArray /*<_ASHierarchyItemChange *>*/ *)itemChangesOfType:(_ASHierarchyChangeType)changeType;
|
||||
|
||||
- (void)deleteSections:(NSIndexSet *)sections animationOptions:(ASDataControllerAnimationOptions)options;
|
||||
- (void)insertSections:(NSIndexSet *)sections animationOptions:(ASDataControllerAnimationOptions)options;
|
||||
- (void)reloadSections:(NSIndexSet *)sections animationOptions:(ASDataControllerAnimationOptions)options;
|
||||
- (void)insertItems:(NSArray<NSIndexPath *> *)indexPaths animationOptions:(ASDataControllerAnimationOptions)options;
|
||||
- (void)deleteItems:(NSArray<NSIndexPath *> *)indexPaths animationOptions:(ASDataControllerAnimationOptions)options;
|
||||
- (void)reloadItems:(NSArray<NSIndexPath *> *)indexPaths animationOptions:(ASDataControllerAnimationOptions)options;
|
||||
- (void)insertItems:(NSArray *)indexPaths animationOptions:(ASDataControllerAnimationOptions)options;
|
||||
- (void)deleteItems:(NSArray *)indexPaths animationOptions:(ASDataControllerAnimationOptions)options;
|
||||
- (void)reloadItems:(NSArray *)indexPaths animationOptions:(ASDataControllerAnimationOptions)options;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@ -12,22 +12,6 @@
|
||||
|
||||
#import "_ASHierarchyChangeSet.h"
|
||||
#import "ASInternalHelpers.h"
|
||||
#import "NSIndexSet+ASHelpers.h"
|
||||
#import "ASAssert.h"
|
||||
|
||||
NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
{
|
||||
switch (changeType) {
|
||||
case _ASHierarchyChangeTypeInsert:
|
||||
return @"Insert";
|
||||
case _ASHierarchyChangeTypeDelete:
|
||||
return @"Delete";
|
||||
case _ASHierarchyChangeTypeReload:
|
||||
return @"Reload";
|
||||
default:
|
||||
return @"(invalid)";
|
||||
}
|
||||
}
|
||||
|
||||
@interface _ASHierarchySectionChange ()
|
||||
- (instancetype)initWithChangeType:(_ASHierarchyChangeType)changeType indexSet:(NSIndexSet *)indexSet animationOptions:(ASDataControllerAnimationOptions)animationOptions;
|
||||
@ -39,7 +23,7 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
+ (void)sortAndCoalesceChanges:(NSMutableArray *)changes;
|
||||
|
||||
/// Returns all the indexes from all the `indexSet`s of the given `_ASHierarchySectionChange` objects.
|
||||
+ (NSMutableIndexSet *)allIndexesInSectionChanges:(NSArray *)changes;
|
||||
+ (NSMutableIndexSet *)allIndexesInChanges:(NSArray *)changes;
|
||||
@end
|
||||
|
||||
@interface _ASHierarchyItemChange ()
|
||||
@ -54,12 +38,12 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
|
||||
@interface _ASHierarchyChangeSet ()
|
||||
|
||||
@property (nonatomic, strong, readonly) NSMutableArray<_ASHierarchyItemChange *> *insertItemChanges;
|
||||
@property (nonatomic, strong, readonly) NSMutableArray<_ASHierarchyItemChange *> *deleteItemChanges;
|
||||
@property (nonatomic, strong, readonly) NSMutableArray<_ASHierarchyItemChange *> *reloadItemChanges;
|
||||
@property (nonatomic, strong, readonly) NSMutableArray<_ASHierarchySectionChange *> *insertSectionChanges;
|
||||
@property (nonatomic, strong, readonly) NSMutableArray<_ASHierarchySectionChange *> *deleteSectionChanges;
|
||||
@property (nonatomic, strong, readonly) NSMutableArray<_ASHierarchySectionChange *> *reloadSectionChanges;
|
||||
@property (nonatomic, strong, readonly) NSMutableArray *insertItemChanges;
|
||||
@property (nonatomic, strong, readonly) NSMutableArray *deleteItemChanges;
|
||||
@property (nonatomic, strong, readonly) NSMutableArray *reloadItemChanges;
|
||||
@property (nonatomic, strong, readonly) NSMutableArray *insertSectionChanges;
|
||||
@property (nonatomic, strong, readonly) NSMutableArray *deleteSectionChanges;
|
||||
@property (nonatomic, strong, readonly) NSMutableArray *reloadSectionChanges;
|
||||
|
||||
@end
|
||||
|
||||
@ -119,27 +103,21 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
}
|
||||
}
|
||||
|
||||
- (NSIndexSet *)indexesForItemChangesOfType:(_ASHierarchyChangeType)changeType inSection:(NSUInteger)section
|
||||
- (NSInteger)newSectionForOldSection:(NSInteger)oldSection
|
||||
{
|
||||
[self _ensureCompleted];
|
||||
NSMutableIndexSet *result = [NSMutableIndexSet indexSet];
|
||||
for (_ASHierarchyItemChange *change in [self itemChangesOfType:changeType]) {
|
||||
[result addIndexes:[NSIndexSet as_indexSetFromIndexPaths:change.indexPaths inSection:section]];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSUInteger)newSectionForOldSection:(NSUInteger)oldSection
|
||||
{
|
||||
ASDisplayNodeAssertNotNil(_deletedSections, @"Cannot call %@ before `markCompleted` returns.", NSStringFromSelector(_cmd));
|
||||
ASDisplayNodeAssertNotNil(_insertedSections, @"Cannot call %@ before `markCompleted` returns.", NSStringFromSelector(_cmd));
|
||||
[self _ensureCompleted];
|
||||
if ([_deletedSections containsIndex:oldSection]) {
|
||||
return NSNotFound;
|
||||
}
|
||||
|
||||
NSUInteger newIndex = oldSection - [_deletedSections countOfIndexesInRange:NSMakeRange(0, oldSection)];
|
||||
newIndex += [_insertedSections as_indexChangeByInsertingItemsBelowIndex:newIndex];
|
||||
__block NSInteger newIndex = oldSection - [_deletedSections countOfIndexesInRange:NSMakeRange(0, oldSection)];
|
||||
[_insertedSections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
if (idx <= newIndex) {
|
||||
newIndex += 1;
|
||||
} else {
|
||||
*stop = YES;
|
||||
}
|
||||
}];
|
||||
return newIndex;
|
||||
}
|
||||
|
||||
@ -202,42 +180,42 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
- (void)_sortAndCoalesceChangeArrays
|
||||
{
|
||||
@autoreleasepool {
|
||||
|
||||
// Split reloaded sections into [delete(oldIndex), insert(newIndex)]
|
||||
|
||||
// Give these their "pre-reloads" values. Once we add in the reloads we'll re-process them.
|
||||
_deletedSections = [_ASHierarchySectionChange allIndexesInSectionChanges:_deleteSectionChanges];
|
||||
_insertedSections = [_ASHierarchySectionChange allIndexesInSectionChanges:_insertSectionChanges];
|
||||
|
||||
for (_ASHierarchySectionChange *change in _reloadSectionChanges) {
|
||||
NSIndexSet *newSections = [change.indexSet as_indexesByMapping:^(NSUInteger idx) {
|
||||
NSUInteger newSec = [self newSectionForOldSection:idx];
|
||||
NSAssert(newSec != NSNotFound, @"Request to reload deleted section %lu", (unsigned long)idx);
|
||||
return newSec;
|
||||
}];
|
||||
|
||||
_ASHierarchySectionChange *deleteChange = [[_ASHierarchySectionChange alloc] initWithChangeType:_ASHierarchyChangeTypeDelete indexSet:change.indexSet animationOptions:change.animationOptions];
|
||||
[_deleteSectionChanges addObject:deleteChange];
|
||||
|
||||
_ASHierarchySectionChange *insertChange = [[_ASHierarchySectionChange alloc] initWithChangeType:_ASHierarchyChangeTypeInsert indexSet:newSections animationOptions:change.animationOptions];
|
||||
[_insertSectionChanges addObject:insertChange];
|
||||
}
|
||||
|
||||
_reloadSectionChanges = nil;
|
||||
|
||||
[_ASHierarchySectionChange sortAndCoalesceChanges:_deleteSectionChanges];
|
||||
[_ASHierarchySectionChange sortAndCoalesceChanges:_insertSectionChanges];
|
||||
_deletedSections = [_ASHierarchySectionChange allIndexesInSectionChanges:_deleteSectionChanges];
|
||||
_insertedSections = [_ASHierarchySectionChange allIndexesInSectionChanges:_insertSectionChanges];
|
||||
[_ASHierarchySectionChange sortAndCoalesceChanges:_reloadSectionChanges];
|
||||
|
||||
// Split reloaded items into [delete(oldIndexPath), insert(newIndexPath)]
|
||||
|
||||
_deletedSections = [[_ASHierarchySectionChange allIndexesInChanges:_deleteSectionChanges] copy];
|
||||
_insertedSections = [[_ASHierarchySectionChange allIndexesInChanges:_insertSectionChanges] copy];
|
||||
_reloadedSections = [[_ASHierarchySectionChange allIndexesInChanges:_reloadSectionChanges] copy];
|
||||
|
||||
// These are invalid old section indexes.
|
||||
NSMutableIndexSet *deletedOrReloaded = [_deletedSections mutableCopy];
|
||||
[deletedOrReloaded addIndexes:_reloadedSections];
|
||||
|
||||
// These are invalid new section indexes.
|
||||
NSMutableIndexSet *insertedOrReloaded = [_insertedSections mutableCopy];
|
||||
|
||||
// Get the new section that each reloaded section index corresponds to.
|
||||
// Coalesce reload sections' indexes into deletes and inserts
|
||||
[_reloadedSections enumerateIndexesUsingBlock:^(NSUInteger oldIndex, __unused BOOL * stop) {
|
||||
NSUInteger newIndex = [self newSectionForOldSection:oldIndex];
|
||||
if (newIndex != NSNotFound) {
|
||||
[insertedOrReloaded addIndex:newIndex];
|
||||
}
|
||||
[deletedOrReloaded addIndex:oldIndex];
|
||||
}];
|
||||
|
||||
_deletedSections = deletedOrReloaded;
|
||||
_insertedSections = insertedOrReloaded;
|
||||
_reloadedSections = nil;
|
||||
|
||||
// reload items changes need to be adjusted so that we access the correct indexPaths in the datasource
|
||||
NSDictionary *insertedIndexPathsMap = [_ASHierarchyItemChange sectionToIndexSetMapFromChanges:_insertItemChanges ofType:_ASHierarchyChangeTypeInsert];
|
||||
NSDictionary *deletedIndexPathsMap = [_ASHierarchyItemChange sectionToIndexSetMapFromChanges:_deleteItemChanges ofType:_ASHierarchyChangeTypeDelete];
|
||||
|
||||
for (_ASHierarchyItemChange *change in _reloadItemChanges) {
|
||||
NSAssert(change.changeType == _ASHierarchyChangeTypeReload, @"It must be a reload change to be in here");
|
||||
NSMutableArray *newIndexPaths = [NSMutableArray arrayWithCapacity:change.indexPaths.count];
|
||||
NSMutableArray *newIndexPaths = [NSMutableArray array];
|
||||
|
||||
// Every indexPaths in the change need to update its section and/or row
|
||||
// depending on all the deletions and insertions
|
||||
@ -245,21 +223,39 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
// - delete/reload indexPaths that are passed in should all be their current indexPaths
|
||||
// - insert indexPaths that are passed in should all be their future indexPaths after deletions
|
||||
for (NSIndexPath *indexPath in change.indexPaths) {
|
||||
NSUInteger section = [self newSectionForOldSection:indexPath.section];
|
||||
NSUInteger item = indexPath.item;
|
||||
__block NSUInteger section = indexPath.section;
|
||||
__block NSUInteger row = indexPath.row;
|
||||
|
||||
|
||||
// Update section number based on section insertions/deletions that are above the current section
|
||||
section -= [_deletedSections countOfIndexesInRange:NSMakeRange(0, section)];
|
||||
[_insertedSections enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
if (idx <= section) {
|
||||
section += 1;
|
||||
} else {
|
||||
*stop = YES;
|
||||
}
|
||||
}];
|
||||
|
||||
// Update row number based on deletions that are above the current row in the current section
|
||||
NSIndexSet *indicesDeletedInSection = deletedIndexPathsMap[@(indexPath.section)];
|
||||
item -= [indicesDeletedInSection countOfIndexesInRange:NSMakeRange(0, item)];
|
||||
row -= [indicesDeletedInSection countOfIndexesInRange:NSMakeRange(0, row)];
|
||||
// Update row number based on insertions that are above the current row in the future section
|
||||
NSIndexSet *indicesInsertedInSection = insertedIndexPathsMap[@(section)];
|
||||
item += [indicesInsertedInSection as_indexChangeByInsertingItemsBelowIndex:item];
|
||||
[indicesInsertedInSection enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
if (idx <= row) {
|
||||
row += 1;
|
||||
} else {
|
||||
*stop = YES;
|
||||
}
|
||||
}];
|
||||
|
||||
NSIndexPath *newIndexPath = [NSIndexPath indexPathForItem:item inSection:section];
|
||||
//TODO: reuse the old indexPath object if section and row aren't changed
|
||||
NSIndexPath *newIndexPath = [NSIndexPath indexPathForRow:row inSection:section];
|
||||
[newIndexPaths addObject:newIndexPath];
|
||||
}
|
||||
|
||||
// All reload changes are translated into deletes and inserts
|
||||
// All reload changes are coalesced into deletes and inserts
|
||||
// We delete the items that needs reload together with other deleted items, at their original index
|
||||
_ASHierarchyItemChange *deleteItemChangeFromReloadChange = [[_ASHierarchyItemChange alloc] initWithChangeType:_ASHierarchyChangeTypeDelete indexPaths:change.indexPaths animationOptions:change.animationOptions presorted:NO];
|
||||
[_deleteItemChanges addObject:deleteItemChangeFromReloadChange];
|
||||
@ -267,20 +263,16 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
_ASHierarchyItemChange *insertItemChangeFromReloadChange = [[_ASHierarchyItemChange alloc] initWithChangeType:_ASHierarchyChangeTypeInsert indexPaths:newIndexPaths animationOptions:change.animationOptions presorted:NO];
|
||||
[_insertItemChanges addObject:insertItemChangeFromReloadChange];
|
||||
}
|
||||
_reloadItemChanges = nil;
|
||||
[_reloadItemChanges removeAllObjects];
|
||||
|
||||
// Ignore item deletes in reloaded/deleted sections.
|
||||
[_ASHierarchyItemChange sortAndCoalesceChanges:_deleteItemChanges ignoringChangesInSections:_deletedSections];
|
||||
[_ASHierarchyItemChange sortAndCoalesceChanges:_deleteItemChanges ignoringChangesInSections:deletedOrReloaded];
|
||||
|
||||
// Ignore item inserts in reloaded(new)/inserted sections.
|
||||
[_ASHierarchyItemChange sortAndCoalesceChanges:_insertItemChanges ignoringChangesInSections:_insertedSections];
|
||||
[_ASHierarchyItemChange sortAndCoalesceChanges:_insertItemChanges ignoringChangesInSections:insertedOrReloaded];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@ %p: deletedSections=%@, insertedSections=%@, deletedItems=%@, insertedItems=%@>", NSStringFromClass(self.class), self, _deletedSections, _insertedSections, _deleteItemChanges, _insertItemChanges];
|
||||
}
|
||||
|
||||
|
||||
@end
|
||||
@ -291,7 +283,6 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
ASDisplayNodeAssert(indexSet.count > 0, @"Request to create _ASHierarchySectionChange with no sections!");
|
||||
_changeType = changeType;
|
||||
_indexSet = indexSet;
|
||||
_animationOptions = animationOptions;
|
||||
@ -355,7 +346,7 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
[changes setArray:result];
|
||||
}
|
||||
|
||||
+ (NSMutableIndexSet *)allIndexesInSectionChanges:(NSArray<_ASHierarchySectionChange *> *)changes
|
||||
+ (NSMutableIndexSet *)allIndexesInChanges:(NSArray *)changes
|
||||
{
|
||||
NSMutableIndexSet *indexes = [NSMutableIndexSet indexSet];
|
||||
for (_ASHierarchySectionChange *change in changes) {
|
||||
@ -364,11 +355,6 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
return indexes;
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@: anim=%lu, type=%@, indexes=%@>", NSStringFromClass(self.class), (unsigned long)_animationOptions, NSStringFromASHierarchyChangeType(_changeType), [self.indexSet as_smallDescription]];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation _ASHierarchyItemChange
|
||||
@ -377,7 +363,6 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
ASDisplayNodeAssert(indexPaths.count > 0, @"Request to create _ASHierarchyItemChange with no items!");
|
||||
_changeType = changeType;
|
||||
if (presorted) {
|
||||
_indexPaths = indexPaths;
|
||||
@ -402,9 +387,9 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
NSNumber *sectionKey = @(indexPath.section);
|
||||
NSMutableIndexSet *indexSet = sectionToIndexSetMap[sectionKey];
|
||||
if (indexSet) {
|
||||
[indexSet addIndex:indexPath.item];
|
||||
[indexSet addIndex:indexPath.row];
|
||||
} else {
|
||||
indexSet = [NSMutableIndexSet indexSetWithIndex:indexPath.item];
|
||||
indexSet = [NSMutableIndexSet indexSetWithIndex:indexPath.row];
|
||||
sectionToIndexSetMap[sectionKey] = indexSet;
|
||||
}
|
||||
}
|
||||
@ -412,7 +397,7 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
return sectionToIndexSetMap;
|
||||
}
|
||||
|
||||
+ (void)sortAndCoalesceChanges:(NSMutableArray *)changes ignoringChangesInSections:(NSIndexSet *)ignoredSections
|
||||
+ (void)sortAndCoalesceChanges:(NSMutableArray *)changes ignoringChangesInSections:(NSIndexSet *)sections
|
||||
{
|
||||
if (changes.count < 1) {
|
||||
return;
|
||||
@ -426,9 +411,12 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
// All changed index paths, sorted
|
||||
NSMutableArray *allIndexPaths = [NSMutableArray new];
|
||||
|
||||
NSPredicate *indexPathInValidSection = [NSPredicate predicateWithBlock:^BOOL(NSIndexPath *indexPath, __unused NSDictionary *_) {
|
||||
return ![sections containsIndex:indexPath.section];
|
||||
}];
|
||||
for (_ASHierarchyItemChange *change in changes) {
|
||||
for (NSIndexPath *indexPath in change.indexPaths) {
|
||||
if (![ignoredSections containsIndex:indexPath.section]) {
|
||||
if ([indexPathInValidSection evaluateWithObject:indexPath]) {
|
||||
animationOptions[indexPath] = @(change.animationOptions);
|
||||
[allIndexPaths addObject:indexPath];
|
||||
}
|
||||
@ -471,9 +459,4 @@ NSString *NSStringFromASHierarchyChangeType(_ASHierarchyChangeType changeType)
|
||||
[changes setArray:result];
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"<%@: anim=%lu, type=%@, indexPaths=%@>", NSStringFromClass(self.class), (unsigned long)_animationOptions, NSStringFromASHierarchyChangeType(_changeType), self.indexPaths];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -200,44 +200,4 @@
|
||||
XCTAssertTrue([(ASTextCellNodeWithSetSelectedCounter *)node setSelectedCounter] == 6, @"setSelected: should not be called on node multiple times.");
|
||||
}
|
||||
|
||||
- (void)testTuningParametersWithExplicitRangeMode
|
||||
{
|
||||
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
|
||||
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
|
||||
|
||||
ASRangeTuningParameters minimumRenderParams = { .leadingBufferScreenfuls = 0.1, .trailingBufferScreenfuls = 0.1 };
|
||||
ASRangeTuningParameters minimumPreloadParams = { .leadingBufferScreenfuls = 0.1, .trailingBufferScreenfuls = 0.1 };
|
||||
ASRangeTuningParameters fullRenderParams = { .leadingBufferScreenfuls = 0.5, .trailingBufferScreenfuls = 0.5 };
|
||||
ASRangeTuningParameters fullPreloadParams = { .leadingBufferScreenfuls = 1, .trailingBufferScreenfuls = 0.5 };
|
||||
|
||||
[collectionView setTuningParameters:minimumRenderParams forRangeMode:ASLayoutRangeModeMinimum rangeType:ASLayoutRangeTypeDisplay];
|
||||
[collectionView setTuningParameters:minimumPreloadParams forRangeMode:ASLayoutRangeModeMinimum rangeType:ASLayoutRangeTypeFetchData];
|
||||
[collectionView setTuningParameters:fullRenderParams forRangeMode:ASLayoutRangeModeFull rangeType:ASLayoutRangeTypeDisplay];
|
||||
[collectionView setTuningParameters:fullPreloadParams forRangeMode:ASLayoutRangeModeFull rangeType:ASLayoutRangeTypeFetchData];
|
||||
|
||||
XCTAssertTrue(ASRangeTuningParametersEqualToRangeTuningParameters(minimumRenderParams,
|
||||
[collectionView tuningParametersForRangeMode:ASLayoutRangeModeMinimum rangeType:ASLayoutRangeTypeDisplay]));
|
||||
XCTAssertTrue(ASRangeTuningParametersEqualToRangeTuningParameters(minimumPreloadParams,
|
||||
[collectionView tuningParametersForRangeMode:ASLayoutRangeModeMinimum rangeType:ASLayoutRangeTypeFetchData]));
|
||||
XCTAssertTrue(ASRangeTuningParametersEqualToRangeTuningParameters(fullRenderParams,
|
||||
[collectionView tuningParametersForRangeMode:ASLayoutRangeModeFull rangeType:ASLayoutRangeTypeDisplay]));
|
||||
XCTAssertTrue(ASRangeTuningParametersEqualToRangeTuningParameters(fullPreloadParams,
|
||||
[collectionView tuningParametersForRangeMode:ASLayoutRangeModeFull rangeType:ASLayoutRangeTypeFetchData]));
|
||||
}
|
||||
|
||||
- (void)testTuningParameters
|
||||
{
|
||||
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
|
||||
ASCollectionView *collectionView = [[ASCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
|
||||
|
||||
ASRangeTuningParameters renderParams = { .leadingBufferScreenfuls = 1.2, .trailingBufferScreenfuls = 3.2 };
|
||||
ASRangeTuningParameters preloadParams = { .leadingBufferScreenfuls = 4.3, .trailingBufferScreenfuls = 2.3 };
|
||||
|
||||
[collectionView setTuningParameters:renderParams forRangeType:ASLayoutRangeTypeDisplay];
|
||||
[collectionView setTuningParameters:preloadParams forRangeType:ASLayoutRangeTypeFetchData];
|
||||
|
||||
XCTAssertTrue(ASRangeTuningParametersEqualToRangeTuningParameters(renderParams, [collectionView tuningParametersForRangeType:ASLayoutRangeTypeDisplay]));
|
||||
XCTAssertTrue(ASRangeTuningParametersEqualToRangeTuningParameters(preloadParams, [collectionView tuningParametersForRangeType:ASLayoutRangeTypeFetchData]));
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -128,6 +128,7 @@
|
||||
return textCellNode;
|
||||
}
|
||||
|
||||
|
||||
- (ASCellNodeBlock)tableView:(ASTableView *)tableView nodeBlockForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
return ^{
|
||||
@ -139,52 +140,12 @@
|
||||
|
||||
@end
|
||||
|
||||
@interface ASTableViewFilledDelegate : NSObject <ASTableViewDelegate>
|
||||
@end
|
||||
|
||||
@implementation ASTableViewFilledDelegate
|
||||
|
||||
- (ASSizeRange)tableView:(ASTableView *)tableView constrainedSizeForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
return ASSizeRangeMakeExactSize(CGSizeMake(10, 42));
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface ASTableViewTests : XCTestCase
|
||||
@property (atomic, retain) ASTableView *testTableView;
|
||||
@end
|
||||
|
||||
@implementation ASTableViewTests
|
||||
|
||||
- (void)testConstrainedSizeForRowAtIndexPath
|
||||
{
|
||||
// Initial width of the table view is non-zero and all nodes are measured with this size.
|
||||
// Any subsequence size change must trigger a relayout.
|
||||
// Width and height are swapped so that a later size change will simulate a rotation
|
||||
ASTestTableView *tableView = [[ASTestTableView alloc] __initWithFrame:CGRectMake(0, 0, 100, 400)
|
||||
style:UITableViewStylePlain];
|
||||
|
||||
ASTableViewFilledDelegate *delegate = [ASTableViewFilledDelegate new];
|
||||
ASTableViewFilledDataSource *dataSource = [ASTableViewFilledDataSource new];
|
||||
|
||||
tableView.asyncDelegate = delegate;
|
||||
tableView.asyncDataSource = dataSource;
|
||||
|
||||
[tableView reloadDataImmediately];
|
||||
[tableView setNeedsLayout];
|
||||
[tableView layoutIfNeeded];
|
||||
|
||||
for (int section = 0; section < NumberOfSections; section++) {
|
||||
for (int row = 0; row < NumberOfRowsPerSection; row++) {
|
||||
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
|
||||
CGRect rect = [tableView rectForRowAtIndexPath:indexPath];
|
||||
XCTAssertEqual(rect.size.width, 100); // specified width should be ignored for table
|
||||
XCTAssertEqual(rect.size.height, 42);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Convert this to ARC.
|
||||
- (void)DISABLED_testTableViewDoesNotRetainItselfAndDelegate
|
||||
{
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
|
||||
@import XCTest;
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
#import "ASTableViewInternal.h"
|
||||
|
||||
// Set to 1 to use UITableView and see if the issue still exists.
|
||||
#define USE_UIKIT_REFERENCE 0
|
||||
@ -20,8 +19,8 @@
|
||||
#define TableView ASTableView
|
||||
#endif
|
||||
|
||||
#define kInitialSectionCount 10
|
||||
#define kInitialItemCount 10
|
||||
#define kInitialSectionCount 20
|
||||
#define kInitialItemCount 20
|
||||
#define kMinimumItemCount 5
|
||||
#define kMinimumSectionCount 3
|
||||
#define kFickleness 0.1
|
||||
@ -146,7 +145,7 @@ static volatile int32_t ASThrashTestSectionNextID = 1;
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
return [NSString stringWithFormat:@"<Section %lu: itemCount=%lu, items=%@>", (unsigned long)_sectionID, (unsigned long)self.items.count, ASThrashArrayDescription(self.items)];
|
||||
return [NSString stringWithFormat:@"<Section %lu: itemCount=%lu>", (unsigned long)_sectionID, (unsigned long)self.items.count];
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone {
|
||||
@ -446,22 +445,17 @@ static NSInteger ASThrashUpdateCurrentSerializationVersion = 1;
|
||||
@implementation ASTableViewThrashTests {
|
||||
// The current update, which will be logged in case of a failure.
|
||||
ASThrashUpdate *_update;
|
||||
BOOL _failed;
|
||||
}
|
||||
|
||||
#pragma mark Overrides
|
||||
|
||||
- (void)tearDown {
|
||||
if (_failed && _update != nil) {
|
||||
NSLog(@"Failed update %@: %@", _update, _update.logFriendlyBase64Representation);
|
||||
}
|
||||
_failed = NO;
|
||||
_update = nil;
|
||||
}
|
||||
|
||||
// NOTE: Despite the documentation, this is not always called if an exception is caught.
|
||||
- (void)recordFailureWithDescription:(NSString *)description inFile:(NSString *)filePath atLine:(NSUInteger)lineNumber expected:(BOOL)expected {
|
||||
_failed = YES;
|
||||
[self logCurrentUpdateIfNeeded];
|
||||
[super recordFailureWithDescription:description inFile:filePath atLine:lineNumber expected:expected];
|
||||
}
|
||||
|
||||
@ -483,12 +477,11 @@ static NSInteger ASThrashUpdateCurrentSerializationVersion = 1;
|
||||
}
|
||||
|
||||
ASThrashDataSource *ds = [[ASThrashDataSource alloc] initWithData:_update.oldData];
|
||||
ds.tableView.test_enableSuperUpdateCallLogging = YES;
|
||||
[self applyUpdate:_update toDataSource:ds];
|
||||
[self verifyDataSource:ds];
|
||||
}
|
||||
|
||||
- (void)testThrashingWildly {
|
||||
- (void)DISABLED_testThrashingWildly {
|
||||
for (NSInteger i = 0; i < kThrashingIterationCount; i++) {
|
||||
[self setUp];
|
||||
ASThrashDataSource *ds = [[ASThrashDataSource alloc] initWithData:[ASThrashTestSection sectionsWithCount:kInitialSectionCount]];
|
||||
@ -502,6 +495,12 @@ static NSInteger ASThrashUpdateCurrentSerializationVersion = 1;
|
||||
|
||||
#pragma mark Helpers
|
||||
|
||||
- (void)logCurrentUpdateIfNeeded {
|
||||
if (_update != nil) {
|
||||
NSLog(@"Failed update %@: %@", _update, _update.logFriendlyBase64Representation);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)applyUpdate:(ASThrashUpdate *)update toDataSource:(ASThrashDataSource *)dataSource {
|
||||
TableView *tableView = dataSource.tableView;
|
||||
|
||||
@ -534,7 +533,7 @@ static NSInteger ASThrashUpdateCurrentSerializationVersion = 1;
|
||||
[tableView waitUntilAllUpdatesAreCommitted];
|
||||
#endif
|
||||
} @catch (NSException *exception) {
|
||||
_failed = YES;
|
||||
[self logCurrentUpdateIfNeeded];
|
||||
@throw exception;
|
||||
}
|
||||
}
|
||||
@ -554,7 +553,7 @@ static NSInteger ASThrashUpdateCurrentSerializationVersion = 1;
|
||||
XCTAssertEqual([tableView rectForRowAtIndexPath:indexPath].size.height, item.rowHeight);
|
||||
#else
|
||||
ASThrashTestNode *node = (ASThrashTestNode *)[tableView nodeForRowAtIndexPath:indexPath];
|
||||
XCTAssertEqualObjects(node.item, item, @"Wrong node at index path %@", indexPath);
|
||||
XCTAssertEqual(node.item, item);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -10,7 +10,7 @@
|
||||
[](https://github.com/Carthage/Carthage)
|
||||
[](https://travis-ci.org/facebook/AsyncDisplayKit)
|
||||
[](https://github.com/facebook/AsyncDisplayKit/blob/master/LICENSE)
|
||||
|
||||
|
||||
|
||||
AsyncDisplayKit is an iOS framework that keeps even the most complex user
|
||||
interfaces smooth and responsive. It was originally built to make Facebook's
|
||||
@ -18,14 +18,14 @@ interfaces smooth and responsive. It was originally built to make Facebook's
|
||||
[pop](https://github.com/facebook/pop)'s physics-based animations — but
|
||||
it's just as powerful with UIKit Dynamics and conventional app designs.
|
||||
|
||||
### Quick start
|
||||
### Quick start
|
||||
|
||||
ASDK is available on [CocoaPods](http://cocoapods.org). Add the following to your Podfile:
|
||||
|
||||
```ruby
|
||||
pod 'AsyncDisplayKit'
|
||||
```
|
||||
|
||||
|
||||
(ASDK can also be used as a regular static library: Copy the project to your
|
||||
codebase manually, adding `AsyncDisplayKit.xcodeproj` to your workspace. Add
|
||||
`libAsyncDisplayKit.a`, MapKit, AssetsLibrary, and Photos to the "Link Binary With
|
||||
@ -46,7 +46,7 @@ CALayers:
|
||||
|
||||
You can construct entire node hierarchies in parallel, or instantiate and size
|
||||
a single node on a background thread — for example, you could do
|
||||
something like this in a UIViewController:
|
||||
something like this in a UIViewController:
|
||||
|
||||
```objective-c
|
||||
dispatch_async(_backgroundQueue, ^{
|
||||
|
||||
40
build.sh
40
build.sh
@ -36,46 +36,6 @@ if [ "$MODE" = "tests" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$MODE" = "examples" ]; then
|
||||
echo "Verifying that all AsyncDisplayKit examples compile."
|
||||
|
||||
for example in examples/*/; do
|
||||
echo "Building (examples) $example."
|
||||
|
||||
if [ -f "${example}/Podfile" ]; then
|
||||
echo "Using CocoaPods"
|
||||
pod install --project-directory=$example
|
||||
|
||||
set -o pipefail && xcodebuild \
|
||||
-workspace "${example}/Sample.xcworkspace" \
|
||||
-scheme Sample \
|
||||
-sdk "$SDK" \
|
||||
-destination "$PLATFORM" \
|
||||
-derivedDataPath ~/ \
|
||||
build | xcpretty $FORMATTER
|
||||
elif [ -f "${example}/Cartfile" ]; then
|
||||
echo "Using Carthage"
|
||||
local_repo=`pwd`
|
||||
current_branch=`git rev-parse --abbrev-ref HEAD`
|
||||
cd $example
|
||||
|
||||
echo "git \"file://${local_repo}\" \"${current_branch}\"" > "Cartfile"
|
||||
carthage update --platform iOS
|
||||
|
||||
set -o pipefail && xcodebuild \
|
||||
-project "Sample.xcodeproj" \
|
||||
-scheme Sample \
|
||||
-sdk "$SDK" \
|
||||
-destination "$PLATFORM" \
|
||||
build | xcpretty $FORMATTER
|
||||
|
||||
cd ../..
|
||||
fi
|
||||
done
|
||||
trap - EXIT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$MODE" = "examples-pt1" ]; then
|
||||
echo "Verifying that all AsyncDisplayKit examples compile."
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user