mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-22 22:25:57 +00:00
[Layout] Move [ASLayoutSpec children] from std::map to NSMutableArray (#2253)
* Initial commit to move [ASLayoutSpec children] from std::map to NSMutableArray * Add NSFastEnumeration to ASLayoutable * ASNullLayoutSpec is a Singleton now * Move ASLayoutSpecPrivate in Private folder * Move to NSArrayPointer and remove ASNullLayoutSpec * Revert "Move to NSArrayPointer and remove ASNullLayoutSpec" This reverts commit 9ab9cf7024b1f6e1984d84fe58af2b84e84cdf94. * Move to childAtIndex: and setChild:atIndex:
This commit is contained in:
committed by
Adlai Holler
parent
8a4d4e3b5c
commit
2f99951732
@@ -206,6 +206,9 @@
|
||||
69708BA61D76386D005C3CF9 /* ASEqualityHashHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 69708BA41D76386D005C3CF9 /* ASEqualityHashHelpers.h */; };
|
||||
69708BA71D76386D005C3CF9 /* ASEqualityHashHelpers.mm in Sources */ = {isa = PBXBuildFile; fileRef = 69708BA51D76386D005C3CF9 /* ASEqualityHashHelpers.mm */; };
|
||||
69708BA81D76386D005C3CF9 /* ASEqualityHashHelpers.mm in Sources */ = {isa = PBXBuildFile; fileRef = 69708BA51D76386D005C3CF9 /* ASEqualityHashHelpers.mm */; };
|
||||
6977965F1D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.h in Headers */ = {isa = PBXBuildFile; fileRef = 6977965D1D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.h */; };
|
||||
697796601D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6977965E1D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.mm */; };
|
||||
697796611D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.mm in Sources */ = {isa = PBXBuildFile; fileRef = 6977965E1D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.mm */; };
|
||||
697B315A1CFE4B410049936F /* ASEditableTextNodeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 697B31591CFE4B410049936F /* ASEditableTextNodeTests.m */; };
|
||||
697C0DE41CF38F28001DE0D4 /* ASLayoutValidation.h in Headers */ = {isa = PBXBuildFile; fileRef = 697C0DE11CF38F28001DE0D4 /* ASLayoutValidation.h */; };
|
||||
697C0DE51CF38F28001DE0D4 /* ASLayoutValidation.mm in Sources */ = {isa = PBXBuildFile; fileRef = 697C0DE21CF38F28001DE0D4 /* ASLayoutValidation.mm */; };
|
||||
@@ -220,6 +223,7 @@
|
||||
69E1006E1CA89CB600D88C1B /* ASEnvironmentInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 69E100691CA89CB600D88C1B /* ASEnvironmentInternal.h */; };
|
||||
69E1006F1CA89CB600D88C1B /* ASEnvironmentInternal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 69E1006A1CA89CB600D88C1B /* ASEnvironmentInternal.mm */; };
|
||||
69E100701CA89CB600D88C1B /* ASEnvironmentInternal.mm in Sources */ = {isa = PBXBuildFile; fileRef = 69E1006A1CA89CB600D88C1B /* ASEnvironmentInternal.mm */; };
|
||||
69EEA0A11D9AB43900B46420 /* ASLayoutSpecPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 69EEA0A01D9AB43900B46420 /* ASLayoutSpecPrivate.h */; };
|
||||
69F10C871C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h in Headers */ = {isa = PBXBuildFile; fileRef = 69F10C851C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
69FEE53D1D95A9AF0086F066 /* ASLayoutableStyleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 69FEE53C1D95A9AF0086F066 /* ASLayoutableStyleTests.m */; };
|
||||
7630FFA81C9E267E007A7C0E /* ASVideoNode.h in Headers */ = {isa = PBXBuildFile; fileRef = AEEC47DF1C20C2DD00EC1693 /* ASVideoNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -985,6 +989,8 @@
|
||||
696FCB301D6E46050093471E /* ASBackgroundLayoutSpecSnapshotTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASBackgroundLayoutSpecSnapshotTests.mm; sourceTree = "<group>"; };
|
||||
69708BA41D76386D005C3CF9 /* ASEqualityHashHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASEqualityHashHelpers.h; path = TextKit/ASEqualityHashHelpers.h; sourceTree = "<group>"; };
|
||||
69708BA51D76386D005C3CF9 /* ASEqualityHashHelpers.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASEqualityHashHelpers.mm; path = TextKit/ASEqualityHashHelpers.mm; sourceTree = "<group>"; };
|
||||
6977965D1D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ASLayoutSpec+Subclasses.h"; path = "AsyncDisplayKit/Layout/ASLayoutSpec+Subclasses.h"; sourceTree = "<group>"; };
|
||||
6977965E1D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = "ASLayoutSpec+Subclasses.mm"; path = "AsyncDisplayKit/Layout/ASLayoutSpec+Subclasses.mm"; sourceTree = "<group>"; };
|
||||
697B31591CFE4B410049936F /* ASEditableTextNodeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASEditableTextNodeTests.m; sourceTree = "<group>"; };
|
||||
697C0DE11CF38F28001DE0D4 /* ASLayoutValidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASLayoutValidation.h; path = AsyncDisplayKit/Layout/ASLayoutValidation.h; sourceTree = "<group>"; };
|
||||
697C0DE21CF38F28001DE0D4 /* ASLayoutValidation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = ASLayoutValidation.mm; path = AsyncDisplayKit/Layout/ASLayoutValidation.mm; sourceTree = "<group>"; };
|
||||
@@ -996,6 +1002,7 @@
|
||||
69CB62AA1CB8165900024920 /* _ASDisplayViewAccessiblity.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _ASDisplayViewAccessiblity.mm; sourceTree = "<group>"; };
|
||||
69E100691CA89CB600D88C1B /* ASEnvironmentInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASEnvironmentInternal.h; sourceTree = "<group>"; };
|
||||
69E1006A1CA89CB600D88C1B /* ASEnvironmentInternal.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASEnvironmentInternal.mm; sourceTree = "<group>"; };
|
||||
69EEA0A01D9AB43900B46420 /* ASLayoutSpecPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASLayoutSpecPrivate.h; sourceTree = "<group>"; };
|
||||
69F10C851C84C35D0026140C /* ASRangeControllerUpdateRangeProtocol+Beta.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "ASRangeControllerUpdateRangeProtocol+Beta.h"; sourceTree = "<group>"; };
|
||||
69FEE53C1D95A9AF0086F066 /* ASLayoutableStyleTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASLayoutableStyleTests.m; sourceTree = "<group>"; };
|
||||
6BDC61F51978FEA400E50D21 /* AsyncDisplayKit.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; path = AsyncDisplayKit.h; sourceTree = "<group>"; };
|
||||
@@ -1527,9 +1534,6 @@
|
||||
058D0A01195D050800B7D73C /* Private */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
CC446A2D1D80AAE00071FD03 /* ASObjectDescriptionHelpers.h */,
|
||||
CC446A2E1D80AAE00071FD03 /* ASObjectDescriptionHelpers.m */,
|
||||
CC54A81B1D70077A00296A24 /* ASDispatch.h */,
|
||||
058D0A02195D050800B7D73C /* _AS-objc-internal.h */,
|
||||
058D0A03195D050800B7D73C /* _ASCoreAnimationExtras.h */,
|
||||
058D0A04195D050800B7D73C /* _ASCoreAnimationExtras.mm */,
|
||||
@@ -1548,6 +1552,7 @@
|
||||
8B0768B21CE752EC002E1453 /* ASDefaultPlaybackButton.m */,
|
||||
AEB7B0181C5962EA00662EF4 /* ASDefaultPlayButton.h */,
|
||||
AEB7B0191C5962EA00662EF4 /* ASDefaultPlayButton.m */,
|
||||
CC54A81B1D70077A00296A24 /* ASDispatch.h */,
|
||||
058D0A08195D050800B7D73C /* ASDisplayNode+AsyncDisplay.mm */,
|
||||
058D0A09195D050800B7D73C /* ASDisplayNode+DebugTiming.h */,
|
||||
058D0A0A195D050800B7D73C /* ASDisplayNode+DebugTiming.mm */,
|
||||
@@ -1563,11 +1568,14 @@
|
||||
058D0A0E195D050800B7D73C /* ASImageNode+CGExtras.m */,
|
||||
ACF6ED431B17847A00DA7C62 /* ASInternalHelpers.h */,
|
||||
ACF6ED441B17847A00DA7C62 /* ASInternalHelpers.m */,
|
||||
69EEA0A01D9AB43900B46420 /* ASLayoutSpecPrivate.h */,
|
||||
ACF6ED451B17847A00DA7C62 /* ASLayoutSpecUtilities.h */,
|
||||
E52405B41C8FEF16004DC8E7 /* ASLayoutTransition.h */,
|
||||
E52405B21C8FEF03004DC8E7 /* ASLayoutTransition.mm */,
|
||||
0442850B1BAA64EC00D16268 /* ASMultidimensionalArrayUtils.h */,
|
||||
0442850C1BAA64EC00D16268 /* ASMultidimensionalArrayUtils.mm */,
|
||||
CC446A2D1D80AAE00071FD03 /* ASObjectDescriptionHelpers.h */,
|
||||
CC446A2E1D80AAE00071FD03 /* ASObjectDescriptionHelpers.m */,
|
||||
CC3B20811C3F76D600798563 /* ASPendingStateController.h */,
|
||||
CC3B20821C3F76D600798563 /* ASPendingStateController.mm */,
|
||||
058D0A10195D050800B7D73C /* ASSentinel.h */,
|
||||
@@ -1677,12 +1685,14 @@
|
||||
ACF6ED0A1B17843500DA7C62 /* ASInsetLayoutSpec.mm */,
|
||||
ACF6ED0B1B17843500DA7C62 /* ASLayout.h */,
|
||||
ACF6ED0C1B17843500DA7C62 /* ASLayout.mm */,
|
||||
9CDC18CB1B910E12004965E2 /* ASLayoutablePrivate.h */,
|
||||
ACF6ED111B17843500DA7C62 /* ASLayoutable.h */,
|
||||
E55D86311CA8A14000A0C26F /* ASLayoutable.mm */,
|
||||
698C8B601CAB49FC0052DC3F /* ASLayoutableExtensibility.h */,
|
||||
9CDC18CB1B910E12004965E2 /* ASLayoutablePrivate.h */,
|
||||
ACF6ED0D1B17843500DA7C62 /* ASLayoutSpec.h */,
|
||||
ACF6ED0E1B17843500DA7C62 /* ASLayoutSpec.mm */,
|
||||
6977965D1D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.h */,
|
||||
6977965E1D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.mm */,
|
||||
697C0DE11CF38F28001DE0D4 /* ASLayoutValidation.h */,
|
||||
697C0DE21CF38F28001DE0D4 /* ASLayoutValidation.mm */,
|
||||
ACF6ED121B17843500DA7C62 /* ASOverlayLayoutSpec.h */,
|
||||
@@ -1775,6 +1785,7 @@
|
||||
254C6B7C1BF94DF4003EC431 /* ASTextKitRenderer+TextChecking.h in Headers */,
|
||||
34EFC7611B701C9C00AD841F /* ASBackgroundLayoutSpec.h in Headers */,
|
||||
68AF37DB1CBEF4D80077BF76 /* ASImageNode+AnimatedImagePrivate.h in Headers */,
|
||||
69EEA0A11D9AB43900B46420 /* ASLayoutSpecPrivate.h in Headers */,
|
||||
B35062591B010F070018CF92 /* ASBaseDefines.h in Headers */,
|
||||
B35062131B010EFD0018CF92 /* ASBasicImageDownloader.h in Headers */,
|
||||
B35062461B010EFD0018CF92 /* ASBasicImageDownloaderInternal.h in Headers */,
|
||||
@@ -1819,6 +1830,7 @@
|
||||
AC7A2C181BDE11DF0093FE1A /* ASTableViewInternal.h in Headers */,
|
||||
B35062531B010EFD0018CF92 /* ASImageNode+CGExtras.h in Headers */,
|
||||
254C6B7F1BF94DF4003EC431 /* ASTextKitTruncating.h in Headers */,
|
||||
6977965F1D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.h in Headers */,
|
||||
7AB338671C55B3460055FDE8 /* ASRelativeLayoutSpec.h in Headers */,
|
||||
B35062021B010EFD0018CF92 /* ASImageNode.h in Headers */,
|
||||
B350621F1B010EFD0018CF92 /* ASImageProtocols.h in Headers */,
|
||||
@@ -2227,6 +2239,7 @@
|
||||
205F0E221B376416007741D0 /* CGRect+ASConvenience.m in Sources */,
|
||||
257754B21BEE44CD00737CA5 /* ASTextKitShadower.mm in Sources */,
|
||||
9CFFC6BE1CCAC52B006A6476 /* ASEnvironment.mm in Sources */,
|
||||
697796601D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.mm in Sources */,
|
||||
058D0A21195D050800B7D73C /* NSMutableAttributedString+TextKitAdditions.m in Sources */,
|
||||
205F0E101B371875007741D0 /* UICollectionViewLayout+ASConvenience.m in Sources */,
|
||||
CC7FD9DF1BB5E962005CCB2B /* ASPhotosFrameworkImageRequest.m in Sources */,
|
||||
@@ -2411,6 +2424,7 @@
|
||||
254C6B871BF94F8A003EC431 /* ASTextKitEntityAttribute.m in Sources */,
|
||||
34566CB31BC1213700715E6B /* ASPhotosFrameworkImageRequest.m in Sources */,
|
||||
254C6B831BF94F8A003EC431 /* ASTextKitCoreTextAdditions.m in Sources */,
|
||||
697796611D8AC8D3007E93D7 /* ASLayoutSpec+Subclasses.mm in Sources */,
|
||||
B350623B1B010EFD0018CF92 /* NSMutableAttributedString+TextKitAdditions.m in Sources */,
|
||||
044284FD1BAA365100D16268 /* UICollectionViewLayout+ASConvenience.m in Sources */,
|
||||
254C6B8A1BF94F8A003EC431 /* ASTextKitRenderer+TextChecking.mm in Sources */,
|
||||
|
||||
@@ -3364,6 +3364,13 @@ static const char *ASDisplayNodeDrawingPriorityKey = "ASDrawingPriority";
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - NSFastEnumeration
|
||||
|
||||
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained _Nullable [_Nonnull])buffer count:(NSUInteger)len
|
||||
{
|
||||
return [self.subnodes countByEnumeratingWithState:state objects:buffer count:len];
|
||||
}
|
||||
|
||||
#pragma mark - ASEnvironment
|
||||
|
||||
- (ASEnvironmentState)environmentState
|
||||
|
||||
@@ -17,11 +17,16 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
@interface ASBackgroundLayoutSpec : ASLayoutSpec
|
||||
|
||||
/**
|
||||
* Background layoutable for this layout spec
|
||||
*/
|
||||
@property (nullable, nonatomic, strong) id<ASLayoutable> background;
|
||||
|
||||
/**
|
||||
@param child A child that is laid out to determine the size of this spec.
|
||||
@param background A layoutable object that is laid out behind the child. If this is nil, the background is omitted.
|
||||
* Creates and returns an ASBackgroundLayoutSpec object
|
||||
*
|
||||
* @param child A child that is laid out to determine the size of this spec.
|
||||
* @param background A layoutable object that is laid out behind the child. If this is nil, the background is omitted.
|
||||
*/
|
||||
+ (instancetype)backgroundLayoutSpecWithChild:(id<ASLayoutable>)child background:(nullable id<ASLayoutable>)background;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
//
|
||||
|
||||
#import "ASBackgroundLayoutSpec.h"
|
||||
#import "ASLayoutSpec+Subclasses.h"
|
||||
|
||||
#import "ASAssert.h"
|
||||
#import "ASLayout.h"
|
||||
@@ -16,11 +17,17 @@
|
||||
static NSUInteger const kForegroundChildIndex = 0;
|
||||
static NSUInteger const kBackgroundChildIndex = 1;
|
||||
|
||||
@interface ASBackgroundLayoutSpec ()
|
||||
@end
|
||||
|
||||
@implementation ASBackgroundLayoutSpec
|
||||
|
||||
#pragma mark - Class
|
||||
|
||||
+ (instancetype)backgroundLayoutSpecWithChild:(id<ASLayoutable>)child background:(id<ASLayoutable>)background;
|
||||
{
|
||||
return [[self alloc] initWithChild:child background:background];
|
||||
}
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
- (instancetype)initWithChild:(id<ASLayoutable>)child background:(id<ASLayoutable>)background
|
||||
{
|
||||
if (!(self = [super init])) {
|
||||
@@ -28,15 +35,12 @@ static NSUInteger const kBackgroundChildIndex = 1;
|
||||
}
|
||||
|
||||
ASDisplayNodeAssertNotNil(child, @"Child cannot be nil");
|
||||
[self setChild:child forIndex:kForegroundChildIndex];
|
||||
[self setChild:child atIndex:kForegroundChildIndex];
|
||||
self.background = background;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)backgroundLayoutSpecWithChild:(id<ASLayoutable>)child background:(id<ASLayoutable>)background;
|
||||
{
|
||||
return [[self alloc] initWithChild:child background:background];
|
||||
}
|
||||
#pragma mark - ASLayoutSpec
|
||||
|
||||
/**
|
||||
* First layout the contents, then fit the background image.
|
||||
@@ -45,7 +49,7 @@ static NSUInteger const kBackgroundChildIndex = 1;
|
||||
restrictedToSize:(ASLayoutableSize)size
|
||||
relativeToParentSize:(CGSize)parentSize
|
||||
{
|
||||
ASLayout *contentsLayout = [self.child layoutThatFits:constrainedSize parentSize:parentSize];
|
||||
ASLayout *contentsLayout = [[super childAtIndex:kForegroundChildIndex] layoutThatFits:constrainedSize parentSize:parentSize];
|
||||
|
||||
NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:2];
|
||||
if (self.background) {
|
||||
@@ -61,14 +65,16 @@ static NSUInteger const kBackgroundChildIndex = 1;
|
||||
return [ASLayout layoutWithLayoutable:self size:contentsLayout.size sublayouts:sublayouts];
|
||||
}
|
||||
|
||||
#pragma mark - Background
|
||||
|
||||
- (void)setBackground:(id<ASLayoutable>)background
|
||||
{
|
||||
[super setChild:background forIndex:kBackgroundChildIndex];
|
||||
[super setChild:background atIndex:kBackgroundChildIndex];
|
||||
}
|
||||
|
||||
- (id<ASLayoutable>)background
|
||||
{
|
||||
return [super childForIndex:kBackgroundChildIndex];
|
||||
return [super childAtIndex:kBackgroundChildIndex];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
64
AsyncDisplayKit/Layout/ASLayoutSpec+Subclasses.h
Normal file
64
AsyncDisplayKit/Layout/ASLayoutSpec+Subclasses.h
Normal file
@@ -0,0 +1,64 @@
|
||||
//
|
||||
// ASLayoutSpec+Subclasses.h
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Michael Schneider on 9/15/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <AsyncDisplayKit/AsyncDisplayKit.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface ASLayoutSpec (Subclassing)
|
||||
|
||||
/**
|
||||
* Helper method for finalLayoutable support
|
||||
*
|
||||
* @warning If you are getting recursion crashes here after implementing finalLayoutable, make sure
|
||||
* that you are setting isFinalLayoutable flag to YES. This must be one BEFORE adding a child
|
||||
* to the new ASLayoutable.
|
||||
*
|
||||
* For example:
|
||||
* - (id<ASLayoutable>)finalLayoutable
|
||||
* {
|
||||
* ASInsetLayoutSpec *insetSpec = [[ASInsetLayoutSpec alloc] init];
|
||||
* insetSpec.insets = UIEdgeInsetsMake(10,10,10,10);
|
||||
* insetSpec.isFinalLayoutable = YES;
|
||||
* [insetSpec setChild:self];
|
||||
* return insetSpec;
|
||||
* }
|
||||
*
|
||||
* @see finalLayoutable
|
||||
*/
|
||||
- (id<ASLayoutable>)layoutableToAddFromLayoutable:(id<ASLayoutable>)child;
|
||||
|
||||
/**
|
||||
* Adds a child with the given identifier to this layout spec.
|
||||
*
|
||||
* @param child A child to be added.
|
||||
*
|
||||
* @param index An index associated with the child.
|
||||
*
|
||||
* @discussion Every ASLayoutSpec must act on at least one child. The ASLayoutSpec base class takes the
|
||||
* responsibility of holding on to the spec children. Some layout specs, like ASInsetLayoutSpec,
|
||||
* only require a single child.
|
||||
*
|
||||
* For layout specs that require a known number of children (ASBackgroundLayoutSpec, for example)
|
||||
* a subclass can use the setChild method to set the "primary" child. It should then use this method
|
||||
* to set any other required children. Ideally a subclass would hide this from the user, and use the
|
||||
* setChild:forIndex: internally. For example, ASBackgroundLayoutSpec exposes a backgroundChild
|
||||
* property that behind the scenes is calling setChild:forIndex:.
|
||||
*/
|
||||
- (void)setChild:(id<ASLayoutable>)child atIndex:(NSUInteger)index;
|
||||
|
||||
/**
|
||||
* Returns the child added to this layout spec using the given index.
|
||||
*
|
||||
* @param index An identifier associated with the the child.
|
||||
*/
|
||||
- (nullable id<ASLayoutable>)childAtIndex:(NSUInteger)index;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
110
AsyncDisplayKit/Layout/ASLayoutSpec+Subclasses.mm
Normal file
110
AsyncDisplayKit/Layout/ASLayoutSpec+Subclasses.mm
Normal file
@@ -0,0 +1,110 @@
|
||||
//
|
||||
// ASLayoutSpec+Subclasses.m
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Michael Schneider on 9/15/16.
|
||||
// Copyright © 2016 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import "ASLayoutSpec+Subclasses.h"
|
||||
#import "ASLayoutSpec.h"
|
||||
#import "ASLayoutSpecPrivate.h"
|
||||
|
||||
#pragma mark - ASNullLayoutSpec
|
||||
|
||||
@interface ASNullLayoutSpec : ASLayoutSpec
|
||||
- (instancetype)init __unavailable;
|
||||
+ (ASNullLayoutSpec *)null;
|
||||
@end
|
||||
|
||||
@implementation ASNullLayoutSpec : ASLayoutSpec
|
||||
|
||||
+ (ASNullLayoutSpec *)null
|
||||
{
|
||||
static ASNullLayoutSpec *sharedNullLayoutSpec = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedNullLayoutSpec = [[self alloc] init];
|
||||
});
|
||||
return sharedNullLayoutSpec;
|
||||
}
|
||||
|
||||
- (BOOL)isMutable
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
|
||||
{
|
||||
return [ASLayout layoutWithLayoutable:self size:CGSizeZero];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark - ASLayoutSpec (Subclassing)
|
||||
|
||||
@implementation ASLayoutSpec (Subclassing)
|
||||
|
||||
#pragma mark - Final layoutable
|
||||
|
||||
- (id<ASLayoutable>)layoutableToAddFromLayoutable:(id<ASLayoutable>)child
|
||||
{
|
||||
if (self.isFinalLayoutable == NO) {
|
||||
id<ASLayoutable> finalLayoutable = [child finalLayoutable];
|
||||
if (finalLayoutable != child) {
|
||||
if (ASEnvironmentStatePropagationEnabled()) {
|
||||
ASEnvironmentStatePropagateUp(finalLayoutable, child.environmentState.layoutOptionsState);
|
||||
} else {
|
||||
// If state propagation is not enabled the layout options state needs to be copied manually
|
||||
ASEnvironmentState finalLayoutableEnvironmentState = finalLayoutable.environmentState;
|
||||
finalLayoutableEnvironmentState.layoutOptionsState = child.environmentState.layoutOptionsState;
|
||||
finalLayoutable.environmentState = finalLayoutableEnvironmentState;
|
||||
}
|
||||
return finalLayoutable;
|
||||
}
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
#pragma mark - Child with index
|
||||
|
||||
- (void)setChild:(id<ASLayoutable>)child atIndex:(NSUInteger)index
|
||||
{
|
||||
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");
|
||||
|
||||
id<ASLayoutable> layoutable = child ? [self layoutableToAddFromLayoutable:child] : [ASNullLayoutSpec null];
|
||||
|
||||
if (child) {
|
||||
if (_childrenArray.count < index) {
|
||||
// Fill up the array with null objects until the index
|
||||
NSInteger i = _childrenArray.count;
|
||||
while (i < index) {
|
||||
_childrenArray[i] = [ASNullLayoutSpec null];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Replace object at the given index with the layoutable
|
||||
_childrenArray[index] = layoutable;
|
||||
|
||||
// TODO: Should we propagate up the layoutable at it could happen that multiple children will propagated up their
|
||||
// layout options and one child will overwrite values from another child
|
||||
// [self propagateUpLayoutable:finalLayoutable];
|
||||
}
|
||||
|
||||
- (id<ASLayoutable>)childAtIndex:(NSUInteger)index
|
||||
{
|
||||
id<ASLayoutable> layoutable = nil;
|
||||
if (index < _childrenArray.count) {
|
||||
layoutable = _childrenArray[index];
|
||||
}
|
||||
|
||||
// Null layoutable should not be accessed
|
||||
ASDisplayNodeAssert(layoutable != [ASNullLayoutSpec null], @"Access child at index without set a child at that index");
|
||||
|
||||
return layoutable;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -25,8 +25,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
@property (nonatomic, assign) BOOL isMutable;
|
||||
|
||||
- (instancetype)init;
|
||||
|
||||
/**
|
||||
* Parent of the layout spec
|
||||
*/
|
||||
@@ -49,25 +47,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
@property (nullable, strong, nonatomic) id<ASLayoutable> child;
|
||||
|
||||
/**
|
||||
* Adds a child with the given identifier to this layout spec.
|
||||
*
|
||||
* @param child A child to be added.
|
||||
*
|
||||
* @param index An index associated with the child.
|
||||
*
|
||||
* @discussion Every ASLayoutSpec must act on at least one child. The ASLayoutSpec base class takes the
|
||||
* responsibility of holding on to the spec children. Some layout specs, like ASInsetLayoutSpec,
|
||||
* only require a single child.
|
||||
*
|
||||
* For layout specs that require a known number of children (ASBackgroundLayoutSpec, for example)
|
||||
* a subclass can use the setChild method to set the "primary" child. It should then use this method
|
||||
* to set any other required children. Ideally a subclass would hide this from the user, and use the
|
||||
* setChild:forIndex: internally. For example, ASBackgroundLayoutSpec exposes a backgroundChild
|
||||
* property that behind the scenes is calling setChild:forIndex:.
|
||||
*/
|
||||
- (void)setChild:(id<ASLayoutable>)child forIndex:(NSUInteger)index;
|
||||
|
||||
/**
|
||||
* Adds childen to this layout spec.
|
||||
*
|
||||
@@ -81,13 +60,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
@property (nullable, strong, nonatomic) NSArray<id<ASLayoutable>> *children;
|
||||
|
||||
/**
|
||||
* Returns the child added to this layout spec using the given index.
|
||||
*
|
||||
* @param index An identifier associated withe the child.
|
||||
*/
|
||||
- (nullable id<ASLayoutable>)childForIndex:(NSUInteger)index;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
@@ -122,4 +94,3 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
|
||||
@@ -9,28 +9,8 @@
|
||||
//
|
||||
|
||||
#import "ASLayoutSpec.h"
|
||||
|
||||
#import "ASAssert.h"
|
||||
#import "ASInternalHelpers.h"
|
||||
#import "ASEnvironmentInternal.h"
|
||||
|
||||
#import "ASLayout.h"
|
||||
#import "ASThread.h"
|
||||
#import "ASTraitCollection.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
#import <map>
|
||||
#import <vector>
|
||||
|
||||
typedef std::map<unsigned long, id<ASLayoutable>, std::less<unsigned long>> ASChildMap;
|
||||
|
||||
@interface ASLayoutSpec() {
|
||||
ASDN::RecursiveMutex __instanceLock__;
|
||||
ASChildMap _children;
|
||||
ASEnvironmentState _environmentState;
|
||||
ASLayoutableStyle *_style;
|
||||
}
|
||||
@end
|
||||
#import "ASLayoutSpecPrivate.h"
|
||||
#import "ASLayoutSpec+Subclasses.h"
|
||||
|
||||
@implementation ASLayoutSpec
|
||||
|
||||
@@ -60,6 +40,7 @@ typedef std::map<unsigned long, id<ASLayoutable>, std::less<unsigned long>> ASCh
|
||||
_isMutable = YES;
|
||||
_environmentState = ASEnvironmentStateMakeDefault();
|
||||
_style = [[ASLayoutableStyle alloc] init];
|
||||
_childrenArray = [[NSMutableArray alloc] init];
|
||||
|
||||
return self;
|
||||
}
|
||||
@@ -74,6 +55,13 @@ typedef std::map<unsigned long, id<ASLayoutable>, std::less<unsigned long>> ASCh
|
||||
return YES;
|
||||
}
|
||||
|
||||
#pragma mark - Final Layoutable
|
||||
|
||||
- (id<ASLayoutable>)finalLayoutable
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Style
|
||||
|
||||
- (ASLayoutableStyle *)style
|
||||
@@ -113,44 +101,8 @@ typedef std::map<unsigned long, id<ASLayoutable>, std::less<unsigned long>> ASCh
|
||||
return [ASLayout layoutWithLayoutable:self size:constrainedSize.min];
|
||||
}
|
||||
|
||||
- (id<ASLayoutable>)finalLayoutable
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id<ASLayoutable>)layoutableToAddFromLayoutable:(id<ASLayoutable>)child
|
||||
{
|
||||
if (self.isFinalLayoutable == NO) {
|
||||
|
||||
// If you are getting recursion crashes here after implementing finalLayoutable, make sure
|
||||
// that you are setting isFinalLayoutable flag to YES. This must be one BEFORE adding a child
|
||||
// to the new ASLayoutable.
|
||||
//
|
||||
// For example:
|
||||
//- (id<ASLayoutable>)finalLayoutable
|
||||
//{
|
||||
// ASInsetLayoutSpec *insetSpec = [[ASInsetLayoutSpec alloc] init];
|
||||
// insetSpec.insets = UIEdgeInsetsMake(10,10,10,10);
|
||||
// insetSpec.isFinalLayoutable = YES;
|
||||
// [insetSpec setChild:self];
|
||||
// return insetSpec;
|
||||
//}
|
||||
|
||||
id<ASLayoutable> finalLayoutable = [child finalLayoutable];
|
||||
if (finalLayoutable != child) {
|
||||
if (ASEnvironmentStatePropagationEnabled()) {
|
||||
ASEnvironmentStatePropagateUp(finalLayoutable, child.environmentState.layoutOptionsState);
|
||||
} else {
|
||||
// If state propagation is not enabled the layout options state needs to be copied manually
|
||||
ASEnvironmentState finalLayoutableEnvironmentState = finalLayoutable.environmentState;
|
||||
finalLayoutableEnvironmentState.layoutOptionsState = child.environmentState.layoutOptionsState;
|
||||
finalLayoutable.environmentState = finalLayoutableEnvironmentState;
|
||||
}
|
||||
return finalLayoutable;
|
||||
}
|
||||
}
|
||||
return child;
|
||||
}
|
||||
#pragma mark - Parent
|
||||
|
||||
- (void)setParent:(id<ASLayoutable>)parent
|
||||
{
|
||||
@@ -162,67 +114,63 @@ typedef std::map<unsigned long, id<ASLayoutable>, std::less<unsigned long>> ASCh
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Child
|
||||
|
||||
- (void)setChild:(id<ASLayoutable>)child
|
||||
{
|
||||
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");
|
||||
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");;
|
||||
ASDisplayNodeAssert(_childrenArray.count < 2, @"This layout spec does not support more than one child. Use the setChildren: or the setChild:AtIndex: API");
|
||||
|
||||
if (child) {
|
||||
id<ASLayoutable> finalLayoutable = [self layoutableToAddFromLayoutable:child];
|
||||
if (finalLayoutable) {
|
||||
_children[0] = finalLayoutable;
|
||||
_childrenArray[0] = finalLayoutable;
|
||||
[self propagateUpLayoutable:finalLayoutable];
|
||||
}
|
||||
} else {
|
||||
_children.erase(0);
|
||||
if (_childrenArray.count) {
|
||||
[_childrenArray removeObjectAtIndex:0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setChild:(id<ASLayoutable>)child forIndex:(NSUInteger)index
|
||||
- (id<ASLayoutable>)child
|
||||
{
|
||||
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");
|
||||
if (child) {
|
||||
id<ASLayoutable> finalLayoutable = [self layoutableToAddFromLayoutable:child];
|
||||
_children[index] = finalLayoutable;
|
||||
} else {
|
||||
_children.erase(index);
|
||||
ASDisplayNodeAssert(_childrenArray.count < 2, @"This layout spec does not support more than one child. Use the setChildren: or the setChild:AtIndex: API");
|
||||
|
||||
if (_childrenArray.count) {
|
||||
return _childrenArray[0];
|
||||
}
|
||||
// TODO: Should we propagate up the layoutable at it could happen that multiple children will propagated up their
|
||||
// layout options and one child will overwrite values from another child
|
||||
// [self propagateUpLayoutable:finalLayoutable];
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark - Children
|
||||
|
||||
- (void)setChildren:(NSArray<id<ASLayoutable>> *)children
|
||||
{
|
||||
ASDisplayNodeAssert(self.isMutable, @"Cannot set properties when layout spec is not mutable");
|
||||
|
||||
_children.clear();
|
||||
[_childrenArray removeAllObjects];
|
||||
|
||||
NSUInteger i = 0;
|
||||
for (id<ASLayoutable> child in children) {
|
||||
_children[i] = [self layoutableToAddFromLayoutable:child];
|
||||
_childrenArray[i] = [self layoutableToAddFromLayoutable:child];
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
- (id<ASLayoutable>)childForIndex:(NSUInteger)index
|
||||
{
|
||||
if (index < _children.size()) {
|
||||
return _children[index];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (id<ASLayoutable>)child
|
||||
{
|
||||
return _children[0];
|
||||
}
|
||||
|
||||
- (NSArray *)children
|
||||
{
|
||||
std::vector<ASLayout *> children;
|
||||
for (ASChildMap::iterator it = _children.begin(); it != _children.end(); ++it ) {
|
||||
children.push_back(it->second);
|
||||
}
|
||||
return [_childrenArray copy];
|
||||
}
|
||||
|
||||
return [NSArray arrayWithObjects:&children[0] count:children.size()];
|
||||
#pragma mark - NSFastEnumeration
|
||||
|
||||
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained _Nullable [_Nonnull])buffer count:(NSUInteger)len
|
||||
{
|
||||
return [_childrenArray countByEnumeratingWithState:state objects:buffer count:len];
|
||||
}
|
||||
|
||||
#pragma mark - ASEnvironment
|
||||
@@ -279,7 +227,6 @@ ASEnvironmentLayoutExtensibilityForwarding
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark - ASWrapperLayoutSpec
|
||||
|
||||
@implementation ASWrapperLayoutSpec
|
||||
|
||||
@@ -50,7 +50,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* access to the options via convenience properties. If you are creating custom layout spec, then you can
|
||||
* extend the backing layout options class to accommodate any new layout options.
|
||||
*/
|
||||
@protocol ASLayoutable <ASEnvironment, ASLayoutablePrivate, ASLayoutableExtensibility>
|
||||
@protocol ASLayoutable <ASEnvironment, ASLayoutablePrivate, ASLayoutableExtensibility, NSFastEnumeration>
|
||||
|
||||
#pragma mark - Getter
|
||||
|
||||
|
||||
@@ -17,8 +17,17 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*/
|
||||
@interface ASOverlayLayoutSpec : ASLayoutSpec
|
||||
|
||||
/**
|
||||
* Overlay layoutable of this layout spec
|
||||
*/
|
||||
@property (nullable, nonatomic, strong) id<ASLayoutable> overlay;
|
||||
|
||||
/**
|
||||
* Creates and returns an ASOverlayLayoutSpec object with a given child and an layoutable that act as overlay.
|
||||
*
|
||||
* @param child A child that is laid out to determine the size of this spec.
|
||||
* @param overlay A layoutable object that is laid out over the child. If this is nil, the overlay is omitted.
|
||||
*/
|
||||
+ (instancetype)overlayLayoutSpecWithChild:(id<ASLayoutable>)child overlay:(nullable id<ASLayoutable>)overlay;
|
||||
|
||||
@end
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
//
|
||||
|
||||
#import "ASOverlayLayoutSpec.h"
|
||||
#import "ASLayoutSpec+Subclasses.h"
|
||||
|
||||
#import "ASAssert.h"
|
||||
#import "ASLayout.h"
|
||||
@@ -18,32 +19,40 @@ static NSUInteger const kOverlayChildIndex = 1;
|
||||
|
||||
@implementation ASOverlayLayoutSpec
|
||||
|
||||
- (instancetype)initWithChild:(id<ASLayoutable>)child overlay:(id<ASLayoutable>)overlay
|
||||
{
|
||||
if (!(self = [super init])) {
|
||||
return nil;
|
||||
}
|
||||
ASDisplayNodeAssertNotNil(child, @"Child that will be overlayed on shouldn't be nil");
|
||||
self.overlay = overlay;
|
||||
[self setChild:child forIndex:kUnderlayChildIndex];
|
||||
return self;
|
||||
}
|
||||
#pragma mark - Class
|
||||
|
||||
+ (instancetype)overlayLayoutSpecWithChild:(id<ASLayoutable>)child overlay:(id<ASLayoutable>)overlay
|
||||
{
|
||||
return [[self alloc] initWithChild:child overlay:overlay];
|
||||
}
|
||||
|
||||
#pragma mark - Lifecycle
|
||||
|
||||
- (instancetype)initWithChild:(id<ASLayoutable>)child overlay:(id<ASLayoutable>)overlay
|
||||
{
|
||||
if (!(self = [super init])) {
|
||||
return nil;
|
||||
}
|
||||
ASDisplayNodeAssertNotNil(child, @"Child that will be overlayed on shouldn't be nil");
|
||||
[self setChild:child atIndex:kUnderlayChildIndex];
|
||||
self.overlay = overlay;
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Setter / Getter
|
||||
|
||||
- (void)setOverlay:(id<ASLayoutable>)overlay
|
||||
{
|
||||
[super setChild:overlay forIndex:kOverlayChildIndex];
|
||||
[super setChild:overlay atIndex:kOverlayChildIndex];
|
||||
}
|
||||
|
||||
- (id<ASLayoutable>)overlay
|
||||
{
|
||||
return [super childForIndex:kOverlayChildIndex];
|
||||
return [super childAtIndex:kOverlayChildIndex];
|
||||
}
|
||||
|
||||
#pragma mark - ASLayoutSpec
|
||||
|
||||
/**
|
||||
First layout the contents, then fit the overlay on top of it.
|
||||
*/
|
||||
@@ -51,7 +60,7 @@ static NSUInteger const kOverlayChildIndex = 1;
|
||||
restrictedToSize:(ASLayoutableSize)size
|
||||
relativeToParentSize:(CGSize)parentSize
|
||||
{
|
||||
ASLayout *contentsLayout = [self.child layoutThatFits:constrainedSize parentSize:parentSize];
|
||||
ASLayout *contentsLayout = [[super childAtIndex:kUnderlayChildIndex] layoutThatFits:constrainedSize parentSize:parentSize];
|
||||
contentsLayout.position = CGPointZero;
|
||||
NSMutableArray *sublayouts = [NSMutableArray arrayWithObject:contentsLayout];
|
||||
if (self.overlay) {
|
||||
|
||||
25
AsyncDisplayKit/Private/ASLayoutSpecPrivate.h
Normal file
25
AsyncDisplayKit/Private/ASLayoutSpecPrivate.h
Normal file
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// ASLayoutSpecPrivate.h
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Michael Schneider on 9/15/16.
|
||||
//
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
//
|
||||
|
||||
|
||||
#import "ASInternalHelpers.h"
|
||||
#import "ASEnvironmentInternal.h"
|
||||
#import "ASThread.h"
|
||||
|
||||
@interface ASLayoutSpec() {
|
||||
ASDN::RecursiveMutex __instanceLock__;
|
||||
ASEnvironmentState _environmentState;
|
||||
ASLayoutableStyle *_style;
|
||||
NSMutableArray *_childrenArray;
|
||||
}
|
||||
@end
|
||||
|
||||
@@ -2070,4 +2070,24 @@ static bool stringContainsPointer(NSString *description, id p) {
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
- (void)testSubnodesFastEnumeration
|
||||
{
|
||||
DeclareNodeNamed(parentNode);
|
||||
DeclareNodeNamed(a);
|
||||
DeclareNodeNamed(b);
|
||||
DeclareNodeNamed(c);
|
||||
DeclareViewNamed(d);
|
||||
|
||||
NSArray *subnodes = @[a, b, c, d];
|
||||
for (ASDisplayNode *node in subnodes) {
|
||||
[parentNode addSubnode:node];
|
||||
}
|
||||
|
||||
NSInteger i = 0;
|
||||
for (ASDisplayNode *subnode in parentNode.subnodes) {
|
||||
XCTAssertEqualObjects(subnode, subnodes[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user