mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-11 08:50:24 +00:00
Faster collection operations (#748)
* Faster collection operations * Fix a few things * Put the stupid semicolon * Address warning * Cut down retain/releases during collection operations * Update CHANGELOG.md
This commit is contained in:
parent
b5d3e52e8b
commit
5c13403ef7
@ -60,6 +60,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
disableMainThreadChecker = "YES"
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
|||||||
@ -14,6 +14,7 @@
|
|||||||
- [ASCollectionNode] Added support for interactive item movement. [Adlai Holler](https://github.com/Adlai-Holler)
|
- [ASCollectionNode] Added support for interactive item movement. [Adlai Holler](https://github.com/Adlai-Holler)
|
||||||
- Added an experimental "no-copy" rendering API. See ASGraphicsContext.h for info. [Adlai Holler](https://github.com/Adlai-Holler)
|
- Added an experimental "no-copy" rendering API. See ASGraphicsContext.h for info. [Adlai Holler](https://github.com/Adlai-Holler)
|
||||||
- Dropped support for iOS 8. [Adlai Holler](https://github.com/Adlai-Holler)
|
- Dropped support for iOS 8. [Adlai Holler](https://github.com/Adlai-Holler)
|
||||||
|
- Optimize internal collection operations. [Adlai Holler](https://github.com/Adlai-Holler) [#748](https://github.com/TextureGroup/Texture/pull/748)
|
||||||
|
|
||||||
## 2.6
|
## 2.6
|
||||||
- [Xcode 9] Updated to require Xcode 9 (to fix warnings) [Garrett Moon](https://github.com/garrettmoon)
|
- [Xcode 9] Updated to require Xcode 9 (to fix warnings) [Garrett Moon](https://github.com/garrettmoon)
|
||||||
|
|||||||
@ -719,19 +719,9 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
|||||||
|
|
||||||
- (NSArray<NSIndexPath *> *)convertIndexPathsToCollectionNode:(NSArray<NSIndexPath *> *)indexPaths
|
- (NSArray<NSIndexPath *> *)convertIndexPathsToCollectionNode:(NSArray<NSIndexPath *> *)indexPaths
|
||||||
{
|
{
|
||||||
if (indexPaths == nil) {
|
return ASArrayByFlatMapping(indexPaths, NSIndexPath *indexPathInView, ({
|
||||||
return nil;
|
[self convertIndexPathToCollectionNode:indexPathInView];
|
||||||
}
|
}));
|
||||||
|
|
||||||
NSMutableArray<NSIndexPath *> *indexPathsArray = [NSMutableArray arrayWithCapacity:indexPaths.count];
|
|
||||||
|
|
||||||
for (NSIndexPath *indexPathInView in indexPaths) {
|
|
||||||
NSIndexPath *indexPath = [self convertIndexPathToCollectionNode:indexPathInView];
|
|
||||||
if (indexPath != nil) {
|
|
||||||
[indexPathsArray addObject:indexPath];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return indexPathsArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (ASCellNode *)supplementaryNodeForElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath
|
- (ASCellNode *)supplementaryNodeForElementKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath
|
||||||
@ -747,17 +737,10 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
|||||||
- (NSArray *)visibleNodes
|
- (NSArray *)visibleNodes
|
||||||
{
|
{
|
||||||
NSArray *indexPaths = [self indexPathsForVisibleItems];
|
NSArray *indexPaths = [self indexPathsForVisibleItems];
|
||||||
NSMutableArray *visibleNodes = [[NSMutableArray alloc] init];
|
|
||||||
|
|
||||||
for (NSIndexPath *indexPath in indexPaths) {
|
return ASArrayByFlatMapping(indexPaths, NSIndexPath *indexPath, ({
|
||||||
ASCellNode *node = [self nodeForItemAtIndexPath:indexPath];
|
[self nodeForItemAtIndexPath:indexPath];
|
||||||
if (node) {
|
}));
|
||||||
// It is possible for UICollectionView to return indexPaths before the node is completed.
|
|
||||||
[visibleNodes addObject:node];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return visibleNodes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)usesSynchronousDataLoading
|
- (BOOL)usesSynchronousDataLoading
|
||||||
@ -2176,13 +2159,9 @@ static NSString * const kReuseIdentifier = @"_ASCollectionReuseIdentifier";
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSMutableArray<NSIndexPath *> *uikitIndexPaths = [NSMutableArray arrayWithCapacity:nodes.count];
|
NSArray *uikitIndexPaths = ASArrayByFlatMapping(nodes, ASCellNode *node, ({
|
||||||
for (ASCellNode *node in nodes) {
|
[self indexPathForNode:node];
|
||||||
NSIndexPath *uikitIndexPath = [self indexPathForNode:node];
|
}));
|
||||||
if (uikitIndexPath != nil) {
|
|
||||||
[uikitIndexPaths addObject:uikitIndexPath];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[_layoutFacilitator collectionViewWillEditCellsAtIndexPaths:uikitIndexPaths batched:NO];
|
[_layoutFacilitator collectionViewWillEditCellsAtIndexPaths:uikitIndexPaths batched:NO];
|
||||||
|
|
||||||
|
|||||||
@ -158,14 +158,12 @@
|
|||||||
- (void)setupYogaCalculatedLayout
|
- (void)setupYogaCalculatedLayout
|
||||||
{
|
{
|
||||||
YGNodeRef yogaNode = self.style.yogaNode;
|
YGNodeRef yogaNode = self.style.yogaNode;
|
||||||
uint32_t childCount = YGNodeGetChildCount(yogaNode);
|
ASDisplayNodeAssert(YGNodeGetChildCount(yogaNode) == self.yogaChildren.count,
|
||||||
ASDisplayNodeAssert(childCount == self.yogaChildren.count,
|
|
||||||
@"Yoga tree should always be in sync with .yogaNodes array! %@", self.yogaChildren);
|
@"Yoga tree should always be in sync with .yogaNodes array! %@", self.yogaChildren);
|
||||||
|
|
||||||
NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:childCount];
|
NSArray *sublayouts = ASArrayByFlatMapping(self.yogaChildren, ASDisplayNode *subnode, ({
|
||||||
for (ASDisplayNode *subnode in self.yogaChildren) {
|
[subnode layoutForYogaNode];
|
||||||
[sublayouts addObject:[subnode layoutForYogaNode]];
|
}));
|
||||||
}
|
|
||||||
|
|
||||||
// The layout for self should have position CGPointNull, but include the calculated size.
|
// The layout for self should have position CGPointNull, but include the calculated size.
|
||||||
CGSize size = CGSizeMake(YGNodeLayoutGetWidth(yogaNode), YGNodeLayoutGetHeight(yogaNode));
|
CGSize size = CGSizeMake(YGNodeLayoutGetWidth(yogaNode), YGNodeLayoutGetHeight(yogaNode));
|
||||||
|
|||||||
@ -607,15 +607,9 @@ static NSString * const kCellReuseIdentifier = @"_ASTableViewCell";
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSMutableArray<NSIndexPath *> *indexPathsArray = [NSMutableArray new];
|
return ASArrayByFlatMapping(indexPaths, NSIndexPath *indexPathInView, ({
|
||||||
|
[self convertIndexPathToTableNode:indexPathInView];
|
||||||
for (NSIndexPath *indexPathInView in indexPaths) {
|
}));
|
||||||
NSIndexPath *indexPath = [self convertIndexPathToTableNode:indexPathInView];
|
|
||||||
if (indexPath != nil) {
|
|
||||||
[indexPathsArray addObject:indexPath];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return indexPathsArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode
|
- (NSIndexPath *)indexPathForNode:(ASCellNode *)cellNode
|
||||||
|
|||||||
@ -132,22 +132,6 @@
|
|||||||
#define __has_attribute(x) 0 // Compatibility with non-clang compilers.
|
#define __has_attribute(x) 0 // Compatibility with non-clang compilers.
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NS_CONSUMED
|
|
||||||
#if __has_feature(attribute_ns_consumed)
|
|
||||||
#define NS_CONSUMED __attribute__((ns_consumed))
|
|
||||||
#else
|
|
||||||
#define NS_CONSUMED
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef NS_RETURNS_RETAINED
|
|
||||||
#if __has_feature(attribute_ns_returns_retained)
|
|
||||||
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
|
|
||||||
#else
|
|
||||||
#define NS_RETURNS_RETAINED
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CF_RETURNS_RETAINED
|
#ifndef CF_RETURNS_RETAINED
|
||||||
#if __has_feature(attribute_cf_returns_retained)
|
#if __has_feature(attribute_cf_returns_retained)
|
||||||
#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
|
#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
|
||||||
@ -245,26 +229,38 @@
|
|||||||
* Create a new set by mapping `collection` over `work`, ignoring nil.
|
* Create a new set by mapping `collection` over `work`, ignoring nil.
|
||||||
*/
|
*/
|
||||||
#define ASSetByFlatMapping(collection, decl, work) ({ \
|
#define ASSetByFlatMapping(collection, decl, work) ({ \
|
||||||
NSMutableSet *s = [NSMutableSet set]; \
|
CFTypeRef _cArray[collection.count]; \
|
||||||
|
NSUInteger _i = 0; \
|
||||||
for (decl in collection) {\
|
for (decl in collection) {\
|
||||||
id result = work; \
|
if ((_cArray[_i] = (__bridge_retained CFTypeRef)work)) { \
|
||||||
if (result != nil) { \
|
_i++; \
|
||||||
[s addObject:result]; \
|
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
s; \
|
NSSet *result; \
|
||||||
|
if (_i == 0) { \
|
||||||
|
/** Zero fast path. */ \
|
||||||
|
result = [NSSet set]; \
|
||||||
|
} else if (_i == 1) { \
|
||||||
|
/** NSSingleObjectSet is fast. Create one and release. */ \
|
||||||
|
CFTypeRef val = _cArray[0]; \
|
||||||
|
result = [NSSet setWithObject:(__bridge id)val]; \
|
||||||
|
CFBridgingRelease(val); \
|
||||||
|
} else { \
|
||||||
|
CFSetCallBacks cb = kCFTypeSetCallBacks; \
|
||||||
|
cb.retain = NULL; \
|
||||||
|
result = (__bridge NSSet *)CFSetCreate(kCFAllocatorDefault, _cArray, _i, &cb); \
|
||||||
|
} \
|
||||||
|
result; \
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new ObjectPointerPersonality NSHashTable by mapping `collection` over `work`, ignoring nil.
|
* Create a new ObjectPointerPersonality NSHashTable by mapping `collection` over `work`, ignoring nil.
|
||||||
*/
|
*/
|
||||||
#define ASPointerTableByFlatMapping(collection, decl, work) ({ \
|
#define ASPointerTableByFlatMapping(collection, decl, work) ({ \
|
||||||
NSHashTable *t = [NSHashTable hashTableWithOptions:NSHashTableObjectPointerPersonality]; \
|
NSHashTable *t = [[NSHashTable alloc] initWithOptions:NSHashTableObjectPointerPersonality capacity:collection.count]; \
|
||||||
for (decl in collection) {\
|
for (decl in collection) {\
|
||||||
id result = work; \
|
/* NSHashTable accepts nil and avoid extra retain/release. */ \
|
||||||
if (result != nil) { \
|
[t addObject:work]; \
|
||||||
[t addObject:result]; \
|
|
||||||
} \
|
|
||||||
} \
|
} \
|
||||||
t; \
|
t; \
|
||||||
})
|
})
|
||||||
@ -273,12 +269,37 @@
|
|||||||
* Create a new array by mapping `collection` over `work`, ignoring nil.
|
* Create a new array by mapping `collection` over `work`, ignoring nil.
|
||||||
*/
|
*/
|
||||||
#define ASArrayByFlatMapping(collection, decl, work) ({ \
|
#define ASArrayByFlatMapping(collection, decl, work) ({ \
|
||||||
NSMutableArray *a = [NSMutableArray array]; \
|
CFTypeRef _cArray[collection.count]; \
|
||||||
|
NSUInteger _i = 0; \
|
||||||
for (decl in collection) {\
|
for (decl in collection) {\
|
||||||
id result = work; \
|
if ((_cArray[_i] = (__bridge_retained CFTypeRef)work)) { \
|
||||||
if (result != nil) { \
|
_i++; \
|
||||||
[a addObject:result]; \
|
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
a; \
|
NSArray *result; \
|
||||||
|
if (_i == 0) { \
|
||||||
|
/** Zero array fast path. */ \
|
||||||
|
result = @[]; \
|
||||||
|
} else if (_i == 1) { \
|
||||||
|
/** NSSingleObjectArray is fast. Create one and release. */ \
|
||||||
|
CFTypeRef val = _cArray[0]; \
|
||||||
|
result = [NSArray arrayWithObject:(__bridge id)val]; \
|
||||||
|
CFBridgingRelease(val); \
|
||||||
|
} else { \
|
||||||
|
CFArrayCallBacks cb = kCFTypeArrayCallBacks; \
|
||||||
|
cb.retain = NULL; \
|
||||||
|
result = (__bridge NSArray *)CFArrayCreate(kCFAllocatorDefault, _cArray, _i, &cb); \
|
||||||
|
} \
|
||||||
|
result; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define ASMutableArrayByFlatMapping(collection, decl, work) ({ \
|
||||||
|
id _cArray[collection.count]; \
|
||||||
|
NSUInteger _i = 0; \
|
||||||
|
for (decl in collection) {\
|
||||||
|
if ((_cArray[_i] = work)) { \
|
||||||
|
_i++; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
[[NSMutableArray alloc] initWithObjects:_cArray count:_i]; \
|
||||||
})
|
})
|
||||||
|
|||||||
@ -59,7 +59,7 @@
|
|||||||
+ (ASCollectionLayoutState *)calculateLayoutWithContext:(ASCollectionLayoutContext *)context
|
+ (ASCollectionLayoutState *)calculateLayoutWithContext:(ASCollectionLayoutContext *)context
|
||||||
{
|
{
|
||||||
ASElementMap *elements = context.elements;
|
ASElementMap *elements = context.elements;
|
||||||
NSMutableArray<ASCellNode *> *children = ASArrayByFlatMapping(elements.itemElements, ASCollectionElement *element, element.node);
|
NSArray<ASCellNode *> *children = ASArrayByFlatMapping(elements.itemElements, ASCollectionElement *element, element.node);
|
||||||
if (children.count == 0) {
|
if (children.count == 0) {
|
||||||
return [[ASCollectionLayoutState alloc] initWithContext:context];
|
return [[ASCollectionLayoutState alloc] initWithContext:context];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -102,9 +102,9 @@
|
|||||||
return [[ASCollectionLayoutState alloc] initWithContext:context];
|
return [[ASCollectionLayoutState alloc] initWithContext:context];
|
||||||
}
|
}
|
||||||
|
|
||||||
NSMutableArray<_ASGalleryLayoutItem *> *children = ASArrayByFlatMapping(elements.itemElements,
|
NSArray<_ASGalleryLayoutItem *> *children = ASArrayByFlatMapping(elements.itemElements,
|
||||||
ASCollectionElement *element,
|
ASCollectionElement *element,
|
||||||
[[_ASGalleryLayoutItem alloc] initWithItemSize:itemSize collectionElement:element]);
|
[[_ASGalleryLayoutItem alloc] initWithItemSize:itemSize collectionElement:element]);
|
||||||
if (children.count == 0) {
|
if (children.count == 0) {
|
||||||
return [[ASCollectionLayoutState alloc] initWithContext:context];
|
return [[ASCollectionLayoutState alloc] initWithContext:context];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,11 @@ NS_ASSUME_NONNULL_BEGIN
|
|||||||
AS_SUBCLASSING_RESTRICTED
|
AS_SUBCLASSING_RESTRICTED
|
||||||
@interface ASElementMap : NSObject <NSCopying, NSFastEnumeration>
|
@interface ASElementMap : NSObject <NSCopying, NSFastEnumeration>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total number of elements in this map.
|
||||||
|
*/
|
||||||
|
@property (readonly) NSUInteger count;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of sections (of items) in this map.
|
* The number of sections (of items) in this map.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -75,6 +75,11 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)count
|
||||||
|
{
|
||||||
|
return _elementToIndexPathMap.count;
|
||||||
|
}
|
||||||
|
|
||||||
- (NSArray<NSIndexPath *> *)itemIndexPaths
|
- (NSArray<NSIndexPath *> *)itemIndexPaths
|
||||||
{
|
{
|
||||||
return ASIndexPathsForTwoDimensionalArray(_sectionsOfItems);
|
return ASIndexPathsForTwoDimensionalArray(_sectionsOfItems);
|
||||||
|
|||||||
@ -203,13 +203,9 @@ static std::atomic_bool static_retainsSublayoutLayoutElements = ATOMIC_VAR_INIT(
|
|||||||
_sublayoutLayoutElements = nil;
|
_sublayoutLayoutElements = nil;
|
||||||
} else {
|
} else {
|
||||||
// Add sublayouts layout elements to an internal array to retain it while the layout lives
|
// Add sublayouts layout elements to an internal array to retain it while the layout lives
|
||||||
NSUInteger sublayoutCount = _sublayouts.count;
|
_sublayoutLayoutElements = ASMutableArrayByFlatMapping(_sublayouts, ASLayout *sublayout, ({
|
||||||
if (sublayoutCount > 0) {
|
sublayout.layoutElement;
|
||||||
_sublayoutLayoutElements = [NSMutableArray arrayWithCapacity:sublayoutCount];
|
}));
|
||||||
for (ASLayout *sublayout in _sublayouts) {
|
|
||||||
[_sublayoutLayoutElements addObject:sublayout.layoutElement];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,7 +232,7 @@ static std::atomic_bool static_retainsSublayoutLayoutElements = ATOMIC_VAR_INIT(
|
|||||||
queue.push_back({sublayout, sublayout.position});
|
queue.push_back({sublayout, sublayout.position});
|
||||||
}
|
}
|
||||||
|
|
||||||
NSMutableArray *flattenedSublayouts = [NSMutableArray array];
|
std::vector<ASLayout *> flattenedSublayouts;
|
||||||
|
|
||||||
while (!queue.empty()) {
|
while (!queue.empty()) {
|
||||||
const Context context = queue.front();
|
const Context context = queue.front();
|
||||||
@ -255,7 +251,7 @@ static std::atomic_bool static_retainsSublayoutLayoutElements = ATOMIC_VAR_INIT(
|
|||||||
position:absolutePosition
|
position:absolutePosition
|
||||||
sublayouts:@[]];
|
sublayouts:@[]];
|
||||||
}
|
}
|
||||||
[flattenedSublayouts addObject:layout];
|
flattenedSublayouts.push_back(layout);
|
||||||
} else if (sublayoutsCount > 0){
|
} else if (sublayoutsCount > 0){
|
||||||
std::vector<Context> sublayoutContexts;
|
std::vector<Context> sublayoutContexts;
|
||||||
for (ASLayout *sublayout in sublayouts) {
|
for (ASLayout *sublayout in sublayouts) {
|
||||||
@ -265,7 +261,8 @@ static std::atomic_bool static_retainsSublayoutLayoutElements = ATOMIC_VAR_INIT(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ASLayout *layout = [ASLayout layoutWithLayoutElement:_layoutElement size:_size sublayouts:flattenedSublayouts];
|
NSArray *sublayoutsArray = [NSArray arrayWithObjects:flattenedSublayouts.data() count:flattenedSublayouts.size()];
|
||||||
|
ASLayout *layout = [ASLayout layoutWithLayoutElement:_layoutElement size:_size sublayouts:sublayoutsArray];
|
||||||
// All flattened layouts must have this flag enabled
|
// All flattened layouts must have this flag enabled
|
||||||
// to ensure sublayout elements are retained until the layouts are applied.
|
// to ensure sublayout elements are retained until the layouts are applied.
|
||||||
layout.retainSublayoutLayoutElements = YES;
|
layout.retainSublayoutLayoutElements = YES;
|
||||||
|
|||||||
@ -295,19 +295,15 @@ ASLayoutElementStyleExtensibilityForwarding
|
|||||||
|
|
||||||
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
|
- (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
|
||||||
{
|
{
|
||||||
NSArray *children = self.children;
|
|
||||||
NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:children.count];
|
|
||||||
|
|
||||||
CGSize size = constrainedSize.min;
|
CGSize size = constrainedSize.min;
|
||||||
for (id<ASLayoutElement> child in children) {
|
NSArray *sublayouts = ASArrayByFlatMapping(self.children, id<ASLayoutElement> child, ({
|
||||||
ASLayout *sublayout = [child layoutThatFits:constrainedSize parentSize:constrainedSize.max];
|
ASLayout *sublayout = [child layoutThatFits:constrainedSize parentSize:constrainedSize.max];
|
||||||
sublayout.position = CGPointZero;
|
sublayout.position = CGPointZero;
|
||||||
|
|
||||||
size.width = MAX(size.width, sublayout.size.width);
|
size.width = MAX(size.width, sublayout.size.width);
|
||||||
size.height = MAX(size.height, sublayout.size.height);
|
size.height = MAX(size.height, sublayout.size.height);
|
||||||
|
sublayout;
|
||||||
[sublayouts addObject:sublayout];
|
}));
|
||||||
}
|
|
||||||
|
|
||||||
return [ASLayout layoutWithLayoutElement:self size:size sublayouts:sublayouts];
|
return [ASLayout layoutWithLayoutElement:self size:size sublayouts:sublayouts];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,13 +27,10 @@
|
|||||||
|
|
||||||
NSMutableArray<NSMutableArray *> *ASTwoDimensionalArrayDeepMutableCopy(NSArray<NSArray *> *array)
|
NSMutableArray<NSMutableArray *> *ASTwoDimensionalArrayDeepMutableCopy(NSArray<NSArray *> *array)
|
||||||
{
|
{
|
||||||
NSMutableArray *newArray = [NSMutableArray arrayWithCapacity:array.count];
|
return ASMutableArrayByFlatMapping(array, NSArray *subarray, ({
|
||||||
NSInteger i = 0;
|
|
||||||
for (NSArray *subarray in array) {
|
|
||||||
ASDisplayNodeCAssert([subarray isKindOfClass:[NSArray class]], @"This function expects NSArray<NSArray *> *");
|
ASDisplayNodeCAssert([subarray isKindOfClass:[NSArray class]], @"This function expects NSArray<NSArray *> *");
|
||||||
newArray[i++] = [subarray mutableCopy];
|
[subarray mutableCopy];
|
||||||
}
|
}));
|
||||||
return newArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASDeleteElementsInTwoDimensionalArrayAtIndexPaths(NSMutableArray *mutableArray, NSArray<NSIndexPath *> *indexPaths)
|
void ASDeleteElementsInTwoDimensionalArrayAtIndexPaths(NSMutableArray *mutableArray, NSArray<NSIndexPath *> *indexPaths)
|
||||||
|
|||||||
@ -69,11 +69,9 @@ NSString * const ASTransitionContextToLayoutKey = @"org.asyncdisplaykit.ASTransi
|
|||||||
|
|
||||||
- (NSArray<ASDisplayNode *> *)subnodesForKey:(NSString *)key
|
- (NSArray<ASDisplayNode *> *)subnodesForKey:(NSString *)key
|
||||||
{
|
{
|
||||||
NSMutableArray<ASDisplayNode *> *subnodes = [NSMutableArray array];
|
return ASArrayByFlatMapping([self layoutForKey:key].sublayouts, ASLayout *sublayout, ({
|
||||||
for (ASLayout *sublayout in [self layoutForKey:key].sublayouts) {
|
(ASDisplayNode *)sublayout.layoutElement;
|
||||||
[subnodes addObject:(ASDisplayNode *)sublayout.layoutElement];
|
}));
|
||||||
}
|
|
||||||
return subnodes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray<ASDisplayNode *> *)insertedSubnodes
|
- (NSArray<ASDisplayNode *> *)insertedSubnodes
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user