mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 22:55:00 +00:00
[Yoga] Initial commit for supporting Yoga-powered layout calculation. (#2982)
* [Yoga + AsyncDisplayKit] Initial commit for supporting Yoga-powered layout calculation. Because this results in ASLayout objects, it preserve support for automaticallyManagesSubnodes as well as the animated transition system. More work remains to vet performance of the new mode, and it will remain in +Beta for the forseeable future. I'm not sure that this should ever be used as the primary ASDK layout system, but it should remain an option for some apps to experiment with if they require an implementation that more strictly mirrors W3C standard Flexbox. * [Yoga] Improve usage of ASHierarchyState to ensure simultaneous yoga layouts can't happen. * [Yoga] Strictly minimize the impact of the Yoga integration on existing code. Created new file ASDisplayNode+Yoga.mm, reduced size and number of integration points in core code. * [Yoga] Figured out how to further reduce ASDisplayNode.mm impact by allocating _yogaNode in property accessor, and changing all accesses to use the property.
This commit is contained in:
@@ -44,6 +44,7 @@ Pod::Spec.new do |spec|
|
||||
end
|
||||
|
||||
spec.subspec 'PINRemoteImage' do |pin|
|
||||
# Note: The core.prefix_header_file includes setup of PIN_REMOTE_IMAGE, so the line below could be removed.
|
||||
pin.xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) PIN_REMOTE_IMAGE=1' }
|
||||
pin.dependency 'PINRemoteImage/iOS', '= 3.0.0-beta.7'
|
||||
pin.dependency 'PINRemoteImage/PINCache'
|
||||
@@ -51,11 +52,17 @@ Pod::Spec.new do |spec|
|
||||
end
|
||||
|
||||
spec.subspec 'IGListKit' do |igl|
|
||||
# Note: The core.prefix_header_file includes setup of IG_LIST_KIT, so the line below could be removed.
|
||||
igl.xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) IG_LIST_KIT=1' }
|
||||
igl.dependency 'IGListKit', '2.1.0'
|
||||
igl.dependency 'AsyncDisplayKit/Core'
|
||||
end
|
||||
|
||||
spec.subspec 'Yoga' do |yoga|
|
||||
yoga.dependency 'Yoga', '1.0.2'
|
||||
yoga.dependency 'AsyncDisplayKit/Core'
|
||||
end
|
||||
|
||||
# Include optional PINRemoteImage module
|
||||
spec.default_subspec = 'PINRemoteImage'
|
||||
|
||||
|
||||
@@ -177,6 +177,7 @@
|
||||
8BBBAB8D1CEBAF1E00107FC6 /* ASDefaultPlaybackButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B0768B21CE752EC002E1453 /* ASDefaultPlaybackButton.m */; };
|
||||
8BDA5FC71CDBDF91007D13B2 /* ASVideoPlayerNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 8BDA5FC31CDBDDE1007D13B2 /* ASVideoPlayerNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
8BDA5FC81CDBDF95007D13B2 /* ASVideoPlayerNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 8BDA5FC41CDBDDE1007D13B2 /* ASVideoPlayerNode.mm */; };
|
||||
90FC784F1E4BFE1B00383C5A /* ASDisplayNode+Yoga.mm in Sources */ = {isa = PBXBuildFile; fileRef = 90FC784E1E4BFE1B00383C5A /* ASDisplayNode+Yoga.mm */; };
|
||||
92DD2FE61BF4D05E0074C9DD /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 92DD2FE51BF4D05E0074C9DD /* MapKit.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
|
||||
92DD2FE71BF4D0850074C9DD /* ASMapNode.mm in Sources */ = {isa = PBXBuildFile; fileRef = 92DD2FE21BF4B97E0074C9DD /* ASMapNode.mm */; };
|
||||
92DD2FE81BF4D0A80074C9DD /* ASMapNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 92DD2FE11BF4B97E0074C9DD /* ASMapNode.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -613,6 +614,7 @@
|
||||
8B0768B21CE752EC002E1453 /* ASDefaultPlaybackButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ASDefaultPlaybackButton.m; sourceTree = "<group>"; };
|
||||
8BDA5FC31CDBDDE1007D13B2 /* ASVideoPlayerNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASVideoPlayerNode.h; sourceTree = "<group>"; };
|
||||
8BDA5FC41CDBDDE1007D13B2 /* ASVideoPlayerNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASVideoPlayerNode.mm; sourceTree = "<group>"; };
|
||||
90FC784E1E4BFE1B00383C5A /* ASDisplayNode+Yoga.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "ASDisplayNode+Yoga.mm"; sourceTree = "<group>"; };
|
||||
92DD2FE11BF4B97E0074C9DD /* ASMapNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASMapNode.h; sourceTree = "<group>"; };
|
||||
92DD2FE21BF4B97E0074C9DD /* ASMapNode.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ASMapNode.mm; sourceTree = "<group>"; };
|
||||
92DD2FE51BF4D05E0074C9DD /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; };
|
||||
@@ -893,6 +895,7 @@
|
||||
058D09D8195D050800B7D73C /* ASDisplayNode.h */,
|
||||
058D09D9195D050800B7D73C /* ASDisplayNode.mm */,
|
||||
68B027791C1A79CC0041016B /* ASDisplayNode+Beta.h */,
|
||||
90FC784E1E4BFE1B00383C5A /* ASDisplayNode+Yoga.mm */,
|
||||
683489271D70DE3400327501 /* ASDisplayNode+Deprecated.h */,
|
||||
058D09DA195D050800B7D73C /* ASDisplayNode+Subclasses.h */,
|
||||
058D09DB195D050800B7D73C /* ASDisplayNodeExtras.h */,
|
||||
@@ -1902,6 +1905,7 @@
|
||||
34EFC76F1B701CF700AD841F /* ASRatioLayoutSpec.mm in Sources */,
|
||||
254C6B8B1BF94F8A003EC431 /* ASTextKitShadower.mm in Sources */,
|
||||
254C6B851BF94F8A003EC431 /* ASTextKitAttributes.mm in Sources */,
|
||||
90FC784F1E4BFE1B00383C5A /* ASDisplayNode+Yoga.mm in Sources */,
|
||||
509E68601B3AED8E009B9150 /* ASScrollDirection.m in Sources */,
|
||||
B35062091B010EFD0018CF92 /* ASScrollNode.mm in Sources */,
|
||||
8BDA5FC81CDBDF95007D13B2 /* ASVideoPlayerNode.mm in Sources */,
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
//
|
||||
|
||||
#import <AsyncDisplayKit/ASAvailability.h>
|
||||
#import <AsyncDisplayKit/ASDisplayNode.h>
|
||||
#import <AsyncDisplayKit/ASLayoutRangeType.h>
|
||||
#import <AsyncDisplayKit/ASEventLog.h>
|
||||
@@ -147,4 +148,38 @@ typedef struct {
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - Yoga Layout Support
|
||||
|
||||
#if YOGA
|
||||
|
||||
@interface ASDisplayNode (Yoga)
|
||||
|
||||
@property (nonatomic, strong) NSArray *yogaChildren;
|
||||
|
||||
- (void)addYogaChild:(ASDisplayNode *)child;
|
||||
- (void)removeYogaChild:(ASDisplayNode *)child;
|
||||
|
||||
// This method should not normally be called directly.
|
||||
- (ASLayout *)calculateLayoutFromYogaRoot:(ASSizeRange)rootConstrainedSize;
|
||||
|
||||
@end
|
||||
|
||||
@interface ASLayoutElementStyle (Yoga)
|
||||
|
||||
@property (nonatomic, assign, readwrite) ASStackLayoutDirection direction;
|
||||
@property (nonatomic, assign, readwrite) CGFloat spacing;
|
||||
@property (nonatomic, assign, readwrite) ASStackLayoutJustifyContent justifyContent;
|
||||
@property (nonatomic, assign, readwrite) ASStackLayoutAlignItems alignItems;
|
||||
@property (nonatomic, assign, readwrite) YGPositionType positionType;
|
||||
@property (nonatomic, assign, readwrite) ASEdgeInsets position;
|
||||
@property (nonatomic, assign, readwrite) ASEdgeInsets margin;
|
||||
@property (nonatomic, assign, readwrite) ASEdgeInsets padding;
|
||||
@property (nonatomic, assign, readwrite) ASEdgeInsets border;
|
||||
@property (nonatomic, assign, readwrite) CGFloat aspectRatio;
|
||||
@property (nonatomic, assign, readwrite) YGWrap flexWrap;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -232,8 +232,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
/** @name Observing node state changes */
|
||||
|
||||
/**
|
||||
* Declare <ASInterfaceState> methods as requiring super calls (this can't be required in the protocol).
|
||||
* For descriptions, see <ASInterfaceState> definition.
|
||||
* Declare <ASInterfaceStateDelegate> methods as requiring super calls (this can't be required in the protocol).
|
||||
* For descriptions, see <ASInterfaceStateDelegate> definition.
|
||||
*/
|
||||
|
||||
- (void)didEnterVisibleState ASDISPLAYNODE_REQUIRES_SUPER;
|
||||
|
||||
407
AsyncDisplayKit/ASDisplayNode+Yoga.mm
Normal file
407
AsyncDisplayKit/ASDisplayNode+Yoga.mm
Normal file
@@ -0,0 +1,407 @@
|
||||
//
|
||||
// ASDisplayNode+Yoga.mm
|
||||
// AsyncDisplayKit
|
||||
//
|
||||
// Created by Scott Goodson on 2/8/17.
|
||||
// Copyright © 2017 Facebook. All rights reserved.
|
||||
//
|
||||
|
||||
#import <AsyncDisplayKit/ASAvailability.h>
|
||||
|
||||
#if YOGA /* YOGA */
|
||||
|
||||
#import <AsyncDisplayKit/ASDisplayNodeInternal.h>
|
||||
#import <AsyncDisplayKit/ASDisplayNode+FrameworkPrivate.h>
|
||||
#import <AsyncDisplayKit/ASDisplayNode+Beta.h>
|
||||
#import <AsyncDisplayKit/ASLayout.h>
|
||||
|
||||
// If Yoga support becomes a supported feature, move this traversal to ASDisplayNodeExtras.
|
||||
void ASDisplayNodePerformBlockOnEveryYogaChild(ASDisplayNode * _Nullable node, void(^block)(ASDisplayNode *node));
|
||||
void ASDisplayNodePerformBlockOnEveryYogaChild(ASDisplayNode * _Nullable node, void(^block)(ASDisplayNode *node))
|
||||
{
|
||||
if (node == nil) {
|
||||
return;
|
||||
}
|
||||
block(node);
|
||||
for (ASDisplayNode *child in [node yogaChildren]) {
|
||||
ASDisplayNodePerformBlockOnEveryYogaChild(child, block);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Yoga Type Conversion Helpers
|
||||
|
||||
YGAlign yogaAlignItems(ASStackLayoutAlignItems alignItems);
|
||||
YGJustify yogaJustifyContent(ASStackLayoutJustifyContent justifyContent);
|
||||
YGAlign yogaAlignSelf(ASStackLayoutAlignSelf alignSelf);
|
||||
YGFlexDirection yogaFlexDirection(ASStackLayoutDirection direction);
|
||||
float yogaFloatForCGFloat(CGFloat value);
|
||||
float yogaDimensionToPoints(ASDimension dimension);
|
||||
float yogaDimensionToPercent(ASDimension dimension);
|
||||
ASDimension dimensionForEdgeWithEdgeInsets(YGEdge edge, ASEdgeInsets insets);
|
||||
YGSize ASLayoutElementYogaMeasureFunc(YGNodeRef yogaNode,
|
||||
float width, YGMeasureMode widthMode,
|
||||
float height, YGMeasureMode heightMode);
|
||||
|
||||
#define YGNODE_STYLE_SET_DIMENSION(yogaNode, property, dimension) \
|
||||
if (dimension.unit == ASDimensionUnitPoints) { \
|
||||
YGNodeStyleSet##property(yogaNode, yogaDimensionToPoints(dimension)); \
|
||||
} else if (dimension.unit == ASDimensionUnitFraction) { \
|
||||
YGNodeStyleSet##property##Percent(yogaNode, yogaDimensionToPercent(dimension)); \
|
||||
} else { \
|
||||
YGNodeStyleSet##property(yogaNode, YGUndefined); \
|
||||
}\
|
||||
|
||||
#define YGNODE_STYLE_SET_DIMENSION_WITH_EDGE(yogaNode, property, dimension, edge) \
|
||||
if (dimension.unit == ASDimensionUnitPoints) { \
|
||||
YGNodeStyleSet##property(yogaNode, edge, yogaDimensionToPoints(dimension)); \
|
||||
} else if (dimension.unit == ASDimensionUnitFraction) { \
|
||||
YGNodeStyleSet##property##Percent(yogaNode, edge, yogaDimensionToPercent(dimension)); \
|
||||
} else { \
|
||||
YGNodeStyleSet##property(yogaNode, edge, YGUndefined); \
|
||||
} \
|
||||
|
||||
#define YGNODE_STYLE_SET_FLOAT_WITH_EDGE(yogaNode, property, dimension, edge) \
|
||||
if (dimension.unit == ASDimensionUnitPoints) { \
|
||||
YGNodeStyleSet##property(yogaNode, edge, yogaDimensionToPoints(dimension)); \
|
||||
} else if (dimension.unit == ASDimensionUnitFraction) { \
|
||||
ASDisplayNodeAssert(NO, @"Unexpected Fraction value in applying ##property## values to YGNode"); \
|
||||
} else { \
|
||||
YGNodeStyleSet##property(yogaNode, edge, YGUndefined); \
|
||||
} \
|
||||
|
||||
YGAlign yogaAlignItems(ASStackLayoutAlignItems alignItems)
|
||||
{
|
||||
switch (alignItems) {
|
||||
case ASStackLayoutAlignItemsStart: return YGAlignFlexStart;
|
||||
case ASStackLayoutAlignItemsEnd: return YGAlignFlexEnd;
|
||||
case ASStackLayoutAlignItemsCenter: return YGAlignCenter;
|
||||
case ASStackLayoutAlignItemsStretch: return YGAlignStretch;
|
||||
case ASStackLayoutAlignItemsBaselineFirst: return YGAlignBaseline;
|
||||
// FIXME: WARNING, Yoga does not currently support last-baseline item alignment.
|
||||
case ASStackLayoutAlignItemsBaselineLast: return YGAlignBaseline;
|
||||
}
|
||||
}
|
||||
|
||||
YGJustify yogaJustifyContent(ASStackLayoutJustifyContent justifyContent)
|
||||
{
|
||||
switch (justifyContent) {
|
||||
case ASStackLayoutJustifyContentStart: return YGJustifyFlexStart;
|
||||
case ASStackLayoutJustifyContentCenter: return YGJustifyCenter;
|
||||
case ASStackLayoutJustifyContentEnd: return YGJustifyFlexEnd;
|
||||
case ASStackLayoutJustifyContentSpaceBetween: return YGJustifySpaceBetween;
|
||||
case ASStackLayoutJustifyContentSpaceAround: return YGJustifySpaceAround;
|
||||
}
|
||||
}
|
||||
|
||||
YGAlign yogaAlignSelf(ASStackLayoutAlignSelf alignSelf)
|
||||
{
|
||||
switch (alignSelf) {
|
||||
case ASStackLayoutAlignSelfStart: return YGAlignFlexStart;
|
||||
case ASStackLayoutAlignSelfCenter: return YGAlignCenter;
|
||||
case ASStackLayoutAlignSelfEnd: return YGAlignFlexEnd;
|
||||
case ASStackLayoutAlignSelfStretch: return YGAlignStretch;
|
||||
case ASStackLayoutAlignSelfAuto: return YGAlignAuto;
|
||||
}
|
||||
}
|
||||
|
||||
YGFlexDirection yogaFlexDirection(ASStackLayoutDirection direction)
|
||||
{
|
||||
return direction == ASStackLayoutDirectionVertical ? YGFlexDirectionColumn : YGFlexDirectionRow;
|
||||
}
|
||||
|
||||
float yogaFloatForCGFloat(CGFloat value)
|
||||
{
|
||||
if (value < CGFLOAT_MAX / 2) {
|
||||
return value;
|
||||
} else {
|
||||
return YGUndefined;
|
||||
}
|
||||
}
|
||||
|
||||
float yogaDimensionToPoints(ASDimension dimension)
|
||||
{
|
||||
ASDisplayNodeCAssert(dimension.unit == ASDimensionUnitPoints,
|
||||
@"Dimensions should not be type Fraction for this method: %f", dimension.value);
|
||||
return yogaFloatForCGFloat(dimension.value);
|
||||
}
|
||||
|
||||
float yogaDimensionToPercent(ASDimension dimension)
|
||||
{
|
||||
ASDisplayNodeCAssert(dimension.unit == ASDimensionUnitFraction,
|
||||
@"Dimensions should not be type Points for this method: %f", dimension.value);
|
||||
return 100.0 * yogaFloatForCGFloat(dimension.value);
|
||||
|
||||
}
|
||||
|
||||
ASDimension dimensionForEdgeWithEdgeInsets(YGEdge edge, ASEdgeInsets insets)
|
||||
{
|
||||
switch (edge) {
|
||||
case YGEdgeLeft: return insets.left;
|
||||
case YGEdgeTop: return insets.top;
|
||||
case YGEdgeRight: return insets.right;
|
||||
case YGEdgeBottom: return insets.bottom;
|
||||
default: ASDisplayNodeCAssert(NO, @"YGEdge other than ASEdgeInsets is not supported.");
|
||||
return ASDimensionAuto;
|
||||
}
|
||||
}
|
||||
|
||||
YGSize ASLayoutElementYogaMeasureFunc(YGNodeRef yogaNode, float width, YGMeasureMode widthMode,
|
||||
float height, YGMeasureMode heightMode)
|
||||
{
|
||||
id <ASLayoutElement> layoutElement = (__bridge id <ASLayoutElement>)YGNodeGetContext(yogaNode);
|
||||
ASSizeRange sizeRange;
|
||||
sizeRange.max = CGSizeMake(width, height);
|
||||
sizeRange.min = sizeRange.max;
|
||||
if (widthMode == YGMeasureModeAtMost) {
|
||||
sizeRange.min.width = 0.0;
|
||||
}
|
||||
if (heightMode == YGMeasureModeAtMost) {
|
||||
sizeRange.min.height = 0.0;
|
||||
}
|
||||
CGSize size = [[layoutElement layoutThatFits:sizeRange] size];
|
||||
return (YGSize){ .width = (float)size.width, .height = (float)size.height };
|
||||
}
|
||||
|
||||
#pragma mark - ASDisplayNode+Yoga
|
||||
|
||||
@interface ASDisplayNode (YogaInternal)
|
||||
@property (nonatomic, weak) ASDisplayNode *yogaParent;
|
||||
@property (nonatomic, assign) YGNodeRef yogaNode;
|
||||
@end
|
||||
|
||||
@implementation ASDisplayNode (Yoga)
|
||||
|
||||
- (void)setYogaNode:(YGNodeRef)yogaNode
|
||||
{
|
||||
_yogaNode = yogaNode;
|
||||
}
|
||||
|
||||
- (YGNodeRef)yogaNode
|
||||
{
|
||||
if (_yogaNode == NULL) {
|
||||
_yogaNode = YGNodeNew();
|
||||
}
|
||||
return _yogaNode;
|
||||
}
|
||||
|
||||
- (void)setYogaParent:(ASDisplayNode *)yogaParent
|
||||
{
|
||||
if (_yogaParent == yogaParent) {
|
||||
return;
|
||||
}
|
||||
|
||||
YGNodeRef yogaNode = self.yogaNode; // Use property to assign Ref if needed.
|
||||
YGNodeRef oldParentRef = YGNodeGetParent(yogaNode);
|
||||
if (oldParentRef != NULL) {
|
||||
YGNodeRemoveChild(oldParentRef, yogaNode);
|
||||
}
|
||||
|
||||
_yogaParent = yogaParent;
|
||||
if (yogaParent) {
|
||||
self.hierarchyState |= ASHierarchyStateYogaLayoutEnabled;
|
||||
YGNodeRef newParentRef = yogaParent.yogaNode;
|
||||
YGNodeInsertChild(newParentRef, yogaNode, YGNodeGetChildCount(newParentRef));
|
||||
} else {
|
||||
self.hierarchyState &= ~ASHierarchyStateYogaLayoutEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
- (ASDisplayNode *)yogaParent
|
||||
{
|
||||
return _yogaParent;
|
||||
}
|
||||
|
||||
- (void)setYogaChildren:(NSArray *)yogaChildren
|
||||
{
|
||||
for (ASDisplayNode *child in _yogaChildren) {
|
||||
// Make sure to un-associate the YGNodeRef tree before replacing _yogaChildren
|
||||
// If this becomes a performance bottleneck, it can be optimized by not doing the NSArray removals here.
|
||||
[self removeYogaChild:child];
|
||||
}
|
||||
_yogaChildren = nil;
|
||||
for (ASDisplayNode *child in yogaChildren) {
|
||||
[self addYogaChild:child];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *)yogaChildren
|
||||
{
|
||||
return _yogaChildren;
|
||||
}
|
||||
|
||||
- (void)addYogaChild:(ASDisplayNode *)child
|
||||
{
|
||||
if (child == nil) {
|
||||
return;
|
||||
}
|
||||
if (_yogaChildren == nil) {
|
||||
_yogaChildren = [NSMutableArray array];
|
||||
}
|
||||
|
||||
// Clean up state in case this child had another parent.
|
||||
[self removeYogaChild:child];
|
||||
|
||||
// YGNodeRef insertion is done in setParent:
|
||||
child.yogaParent = self;
|
||||
[_yogaChildren addObject:child];
|
||||
|
||||
self.hierarchyState |= ASHierarchyStateYogaLayoutEnabled;
|
||||
}
|
||||
|
||||
- (void)removeYogaChild:(ASDisplayNode *)child
|
||||
{
|
||||
if (child == nil) {
|
||||
return;
|
||||
}
|
||||
// YGNodeRef removal is done in setParent:
|
||||
child.yogaParent = nil;
|
||||
[_yogaChildren removeObjectIdenticalTo:child];
|
||||
|
||||
if (_yogaChildren.count == 0 && self.yogaParent == nil) {
|
||||
self.hierarchyState &= ~ASHierarchyStateYogaLayoutEnabled;
|
||||
}
|
||||
}
|
||||
|
||||
- (ASLayout *)layoutTreeForYogaNode
|
||||
{
|
||||
YGNodeRef yogaNode = self.yogaNode; // Use property to assign Ref if needed.
|
||||
uint32_t childCount = YGNodeGetChildCount(yogaNode);
|
||||
ASDisplayNodeAssert(childCount == self.yogaChildren.count,
|
||||
@"Yoga tree should always be in sync with .yogaNodes array! %@", self.yogaChildren);
|
||||
|
||||
NSMutableArray *sublayouts = [NSMutableArray arrayWithCapacity:childCount];
|
||||
for (ASDisplayNode *subnode in self.yogaChildren) {
|
||||
[sublayouts addObject:[subnode layoutTreeForYogaNode]];
|
||||
}
|
||||
|
||||
CGSize size = CGSizeMake(YGNodeLayoutGetWidth(yogaNode), YGNodeLayoutGetHeight(yogaNode));
|
||||
CGPoint position = CGPointMake(YGNodeLayoutGetLeft(yogaNode), YGNodeLayoutGetTop(yogaNode));
|
||||
|
||||
ASDisplayNodeLogEvent(self, @"Yoga calculatedSize: %@", NSStringFromCGSize(size));
|
||||
|
||||
ASLayout *layout = [ASLayout layoutWithLayoutElement:self
|
||||
size:size
|
||||
position:position
|
||||
sublayouts:sublayouts];
|
||||
return layout;
|
||||
}
|
||||
|
||||
- (void)setYogaMeasureFuncIfNeeded
|
||||
{
|
||||
// Manual size calculation via calculateSizeThatFits:
|
||||
// This will be used for ASTextNode, as well as any other leaf node that has no layout spec.
|
||||
if ((self.methodOverrides & ASDisplayNodeMethodOverrideLayoutSpecThatFits) == NO
|
||||
&& self.layoutSpecBlock == NULL && self.yogaChildren.count == 0) {
|
||||
YGNodeRef yogaNode = self.yogaNode; // Use property to assign Ref if needed.
|
||||
YGNodeSetContext(yogaNode, (__bridge void *)self);
|
||||
YGNodeSetMeasureFunc(yogaNode, &ASLayoutElementYogaMeasureFunc);
|
||||
}
|
||||
}
|
||||
|
||||
- (ASLayout *)calculateLayoutFromYogaRoot:(ASSizeRange)rootConstrainedSize
|
||||
{
|
||||
if (ASHierarchyStateIncludesYogaLayoutMeasuring(self.hierarchyState)) {
|
||||
ASDisplayNodeAssert(NO, @"A Yoga layout is being performed by a parent; children must not perform their own until it is done! %@", [self displayNodeRecursiveDescription]);
|
||||
return [ASLayout layoutWithLayoutElement:self size:CGSizeZero];
|
||||
}
|
||||
|
||||
ASDisplayNodePerformBlockOnEveryYogaChild(self, ^(ASDisplayNode * _Nonnull node) {
|
||||
node.hierarchyState |= ASHierarchyStateYogaLayoutMeasuring;
|
||||
});
|
||||
|
||||
YGNodeRef rootYogaNode = self.yogaNode;
|
||||
|
||||
// Apply the constrainedSize as a base, known frame of reference.
|
||||
// If the root node also has style.*Size set, these will be overridden below.
|
||||
YGNodeStyleSetMinWidth (rootYogaNode, yogaFloatForCGFloat(rootConstrainedSize.min.width));
|
||||
YGNodeStyleSetMinHeight(rootYogaNode, yogaFloatForCGFloat(rootConstrainedSize.min.height));
|
||||
|
||||
// TODO(appleguy); Is it sufficient to set only Width OR MaxWidth (+ same for height), or do we need all four?
|
||||
YGNodeStyleSetMaxWidth (rootYogaNode, yogaFloatForCGFloat(rootConstrainedSize.max.width));
|
||||
YGNodeStyleSetMaxHeight(rootYogaNode, yogaFloatForCGFloat(rootConstrainedSize.max.height));
|
||||
YGNodeStyleSetWidth (rootYogaNode, yogaFloatForCGFloat(rootConstrainedSize.max.width));
|
||||
YGNodeStyleSetHeight (rootYogaNode, yogaFloatForCGFloat(rootConstrainedSize.max.height));
|
||||
|
||||
// TODO(appleguy): We need this on all containers, not just the root. Need to be able to check for "unset"
|
||||
YGNodeStyleSetAlignItems(rootYogaNode, yogaAlignItems(self.style.alignItems));
|
||||
|
||||
ASDisplayNodePerformBlockOnEveryYogaChild(self, ^(ASDisplayNode * _Nonnull node) {
|
||||
ASLayoutElementStyle *style = node.style;
|
||||
YGNodeRef yogaNode = node.yogaNode;
|
||||
|
||||
YGNodeStyleSetDirection (yogaNode, YGDirectionInherit);
|
||||
|
||||
YGNodeStyleSetFlexWrap (yogaNode, style.flexWrap);
|
||||
YGNodeStyleSetFlexGrow (yogaNode, style.flexGrow);
|
||||
YGNodeStyleSetFlexShrink (yogaNode, style.flexShrink);
|
||||
YGNODE_STYLE_SET_DIMENSION (yogaNode, FlexBasis, style.flexBasis);
|
||||
|
||||
YGNodeStyleSetFlexDirection (yogaNode, yogaFlexDirection(style.direction));
|
||||
YGNodeStyleSetAlignSelf (yogaNode, yogaAlignSelf(style.alignSelf));
|
||||
YGNodeStyleSetAlignItems (yogaNode, yogaAlignItems(style.alignItems));
|
||||
YGNodeStyleSetJustifyContent(yogaNode, yogaJustifyContent(style.justifyContent));
|
||||
|
||||
YGNodeStyleSetPositionType (yogaNode, style.positionType);
|
||||
|
||||
ASEdgeInsets position = style.position;
|
||||
ASEdgeInsets margin = style.margin;
|
||||
ASEdgeInsets padding = style.padding;
|
||||
ASEdgeInsets border = style.border;
|
||||
|
||||
YGEdge edge = YGEdgeLeft;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
YGNODE_STYLE_SET_DIMENSION_WITH_EDGE(yogaNode, Position, dimensionForEdgeWithEdgeInsets(edge, position), edge);
|
||||
YGNODE_STYLE_SET_DIMENSION_WITH_EDGE(yogaNode, Margin, dimensionForEdgeWithEdgeInsets(edge, margin), edge);
|
||||
YGNODE_STYLE_SET_DIMENSION_WITH_EDGE(yogaNode, Padding, dimensionForEdgeWithEdgeInsets(edge, padding), edge);
|
||||
YGNODE_STYLE_SET_FLOAT_WITH_EDGE(yogaNode, Border, dimensionForEdgeWithEdgeInsets(edge, border), edge);
|
||||
edge = (edge == YGEdgeLeft ? YGEdgeTop : (edge == YGEdgeTop ? YGEdgeRight : YGEdgeBottom));
|
||||
}
|
||||
|
||||
CGFloat aspectRatio = style.aspectRatio;
|
||||
if (aspectRatio > FLT_EPSILON && aspectRatio < CGFLOAT_MAX / 2.0) {
|
||||
YGNodeStyleSetAspectRatio(yogaNode, aspectRatio);
|
||||
}
|
||||
|
||||
// For the root node, we use rootConstrainedSize above. For children, consult the style for their size.
|
||||
if (node != self) {
|
||||
YGNODE_STYLE_SET_DIMENSION(yogaNode, Width, style.width);
|
||||
YGNODE_STYLE_SET_DIMENSION(yogaNode, Height, style.height);
|
||||
|
||||
YGNODE_STYLE_SET_DIMENSION(yogaNode, MinWidth, style.minWidth);
|
||||
YGNODE_STYLE_SET_DIMENSION(yogaNode, MinHeight, style.minHeight);
|
||||
|
||||
YGNODE_STYLE_SET_DIMENSION(yogaNode, MaxWidth, style.maxWidth);
|
||||
YGNODE_STYLE_SET_DIMENSION(yogaNode, MaxHeight, style.maxHeight);
|
||||
}
|
||||
|
||||
[node setYogaMeasureFuncIfNeeded];
|
||||
|
||||
/* TODO(appleguy): STYLE SETTER METHODS LEFT TO IMPLEMENT
|
||||
void YGNodeStyleSetFlexDirection(YGNodeRef node, YGFlexDirection flexDirection);
|
||||
void YGNodeStyleSetOverflow(YGNodeRef node, YGOverflow overflow);
|
||||
void YGNodeStyleSetFlex(YGNodeRef node, float flex);
|
||||
*/
|
||||
});
|
||||
|
||||
// It is crucial to use yogaFloat... to convert CGFLOAT_MAX into YGUndefined here.
|
||||
YGNodeCalculateLayout(rootYogaNode,
|
||||
yogaFloatForCGFloat(rootConstrainedSize.max.width),
|
||||
yogaFloatForCGFloat(rootConstrainedSize.max.height),
|
||||
YGDirectionInherit);
|
||||
|
||||
#if ASEVENTLOG_ENABLE
|
||||
YGNodePrint(rootYogaNode, (YGPrintOptions)(YGPrintOptionsChildren | YGPrintOptionsStyle | YGPrintOptionsLayout));
|
||||
#endif
|
||||
|
||||
ASLayout *yogaLayout = [self layoutTreeForYogaNode];
|
||||
|
||||
ASDisplayNodePerformBlockOnEveryYogaChild(self, ^(ASDisplayNode * _Nonnull node) {
|
||||
node.hierarchyState &= ~ASHierarchyStateYogaLayoutMeasuring;
|
||||
});
|
||||
|
||||
return yogaLayout;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif /* YOGA */
|
||||
@@ -427,6 +427,12 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
|
||||
|
||||
_subnodes = nil;
|
||||
|
||||
#if YOGA
|
||||
if (_yogaNode != NULL) {
|
||||
YGNodeFree(_yogaNode);
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: Remove this? If supernode isn't already nil, this method isn't dealloc-safe anyway.
|
||||
[self __setSupernode:nil];
|
||||
}
|
||||
@@ -1070,7 +1076,8 @@ ASLayoutElementFinalLayoutElementDefault
|
||||
restrictedToSize:(ASLayoutElementSize)size
|
||||
relativeToParentSize:(CGSize)parentSize
|
||||
{
|
||||
const ASSizeRange resolvedRange = ASSizeRangeIntersect(constrainedSize, ASLayoutElementSizeResolve(self.style.size, parentSize));
|
||||
ASSizeRange styleAndParentSize = ASLayoutElementSizeResolve(self.style.size, parentSize);
|
||||
const ASSizeRange resolvedRange = ASSizeRangeIntersect(constrainedSize, styleAndParentSize);
|
||||
return [self calculateLayoutThatFits:resolvedRange];
|
||||
}
|
||||
|
||||
@@ -1080,6 +1087,14 @@ ASLayoutElementFinalLayoutElementDefault
|
||||
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
|
||||
#if YOGA /* YOGA */
|
||||
if (ASHierarchyStateIncludesYogaLayoutEnabled(_hierarchyState) == YES &&
|
||||
ASHierarchyStateIncludesYogaLayoutMeasuring(_hierarchyState) == NO) {
|
||||
ASDN::MutexUnlocker ul(__instanceLock__);
|
||||
return [self calculateLayoutFromYogaRoot:constrainedSize];
|
||||
}
|
||||
#endif /* YOGA */
|
||||
|
||||
// Manual size calculation via calculateSizeThatFits:
|
||||
if (((_methodOverrides & ASDisplayNodeMethodOverrideLayoutSpecThatFits) ||
|
||||
(_layoutSpecBlock != NULL)) == NO) {
|
||||
@@ -3189,13 +3204,11 @@ ASDISPLAYNODE_INLINE BOOL nodeIsInRasterizedTree(ASDisplayNode *node) {
|
||||
// Entering layout pending state
|
||||
} else {
|
||||
// Leaving layout pending state, reset related properties
|
||||
{
|
||||
ASDN::MutexLocker l(__instanceLock__);
|
||||
_pendingTransitionID = ASLayoutElementContextInvalidTransitionID;
|
||||
_pendingLayoutTransition = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ASDisplayNodeLogEvent(self, @"setHierarchyState: oldState = %@, newState = %@", NSStringFromASHierarchyState(oldState), NSStringFromASHierarchyState(newState));
|
||||
}
|
||||
|
||||
@@ -8,10 +8,11 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#endif
|
||||
|
||||
// Some build systems (Cocoapods, Buck, Bazel, etc) will define these flags manually if the functionality
|
||||
// is needed by the app. Carthage in particular, or if a user forgets to set the build flag, benefit from
|
||||
// checking if each flag is not defined and then setting it to whether or not the header is accessible.
|
||||
|
||||
// CocoaPods has a preproceessor macro for PIN_REMOTE_IMAGE, if already defined, okay
|
||||
#ifndef PIN_REMOTE_IMAGE
|
||||
|
||||
// For Carthage or manual builds, this will define PIN_REMOTE_IMAGE if the header is available in the
|
||||
// search path e.g. they've dragged in the framework (technically this will not be able to detect if
|
||||
// a user does not include the framework in the link binary with build step).
|
||||
|
||||
@@ -191,6 +191,15 @@ ASDISPLAYNODE_INLINE AS_WARN_UNUSED_RESULT NSString *NSStringFromASLayoutSize(AS
|
||||
NSStringFromASDimension(size.height)];
|
||||
}
|
||||
|
||||
#pragma mark - ASEdgeInsets
|
||||
|
||||
typedef struct {
|
||||
ASDimension top;
|
||||
ASDimension left;
|
||||
ASDimension bottom;
|
||||
ASDimension right;
|
||||
} ASEdgeInsets;
|
||||
|
||||
#pragma mark - ASSizeRange
|
||||
|
||||
/**
|
||||
|
||||
@@ -157,6 +157,8 @@ ASDISPLAYNODE_EXTERN_C_END
|
||||
|
||||
#pragma mark - Deprecated
|
||||
|
||||
#define ASLayoutable ASLayoutElement
|
||||
|
||||
/**
|
||||
* @abstract Calculate a layout based on given size range.
|
||||
*
|
||||
@@ -259,7 +261,6 @@ extern NSString * const ASLayoutElementStyleLayoutPositionProperty;
|
||||
*/
|
||||
@property (nonatomic, assign, readwrite) ASDimension maxWidth;
|
||||
|
||||
|
||||
#pragma mark - ASLayoutElementStyleSizeHelpers
|
||||
|
||||
/**
|
||||
@@ -325,7 +326,6 @@ extern NSString * const ASLayoutElementStyleLayoutPositionProperty;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#pragma mark - ASLayoutElementStylability
|
||||
|
||||
@protocol ASLayoutElementStylability
|
||||
|
||||
@@ -10,13 +10,14 @@
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
//
|
||||
|
||||
#import "ASDisplayNode+FrameworkPrivate.h"
|
||||
#import <AsyncDisplayKit/ASLayout.h>
|
||||
#import <AsyncDisplayKit/ASLayoutElement.h>
|
||||
#import <AsyncDisplayKit/ASThread.h>
|
||||
#import <AsyncDisplayKit/ASObjectDescriptionHelpers.h>
|
||||
|
||||
#import <map>
|
||||
#import <atomic>
|
||||
#import <AsyncDisplayKit/ASThread.h>
|
||||
|
||||
#import <AsyncDisplayKit/ASObjectDescriptionHelpers.h>
|
||||
|
||||
extern void ASLayoutElementPerformBlockOnEveryElement(id<ASLayoutElement> element, void(^block)(id<ASLayoutElement> element))
|
||||
{
|
||||
@@ -138,6 +139,20 @@ do {\
|
||||
std::atomic<CGFloat> _ascender;
|
||||
std::atomic<CGFloat> _descender;
|
||||
std::atomic<CGPoint> _layoutPosition;
|
||||
|
||||
#if YOGA
|
||||
std::atomic<ASStackLayoutDirection> _direction;
|
||||
std::atomic<CGFloat> _spacing;
|
||||
std::atomic<ASStackLayoutJustifyContent> _justifyContent;
|
||||
std::atomic<ASStackLayoutAlignItems> _alignItems;
|
||||
std::atomic<YGPositionType> _positionType;
|
||||
std::atomic<ASEdgeInsets> _position;
|
||||
std::atomic<ASEdgeInsets> _margin;
|
||||
std::atomic<ASEdgeInsets> _padding;
|
||||
std::atomic<ASEdgeInsets> _border;
|
||||
std::atomic<CGFloat> _aspectRatio;
|
||||
std::atomic<YGWrap> _flexWrap;
|
||||
#endif
|
||||
}
|
||||
|
||||
@dynamic width, height, minWidth, maxWidth, minHeight, maxHeight;
|
||||
@@ -350,7 +365,6 @@ do {\
|
||||
ASLayoutElementStyleCallDelegate(ASLayoutElementStyleMaxHeightProperty);
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - ASStackLayoutElement
|
||||
|
||||
- (void)setSpacingBefore:(CGFloat)spacingBefore
|
||||
@@ -573,6 +587,36 @@ do {\
|
||||
return result;
|
||||
}
|
||||
|
||||
#pragma mark - Yoga Flexbox Properties
|
||||
|
||||
#if YOGA
|
||||
|
||||
- (ASStackLayoutDirection)direction { return _direction.load(); }
|
||||
- (CGFloat)spacing { return _spacing.load(); }
|
||||
- (ASStackLayoutJustifyContent)justifyContent { return _justifyContent.load(); }
|
||||
- (ASStackLayoutAlignItems)alignItems { return _alignItems.load(); }
|
||||
- (YGPositionType)positionType { return _positionType.load(); }
|
||||
- (ASEdgeInsets)position { return _position.load(); }
|
||||
- (ASEdgeInsets)margin { return _margin.load(); }
|
||||
- (ASEdgeInsets)padding { return _padding.load(); }
|
||||
- (ASEdgeInsets)border { return _border.load(); }
|
||||
- (CGFloat)aspectRatio { return _aspectRatio.load(); }
|
||||
- (YGWrap)flexWrap { return _flexWrap.load(); }
|
||||
|
||||
- (void)setDirection:(ASStackLayoutDirection)direction { _direction.store(direction); }
|
||||
- (void)setSpacing:(CGFloat)spacing { _spacing.store(spacing); }
|
||||
- (void)setJustifyContent:(ASStackLayoutJustifyContent)justify { _justifyContent.store(justify); }
|
||||
- (void)setAlignItems:(ASStackLayoutAlignItems)alignItems { _alignItems.store(alignItems); }
|
||||
- (void)setPositionType:(YGPositionType)positionType { _positionType.store(positionType); }
|
||||
- (void)setPosition:(ASEdgeInsets)position { _position.store(position); }
|
||||
- (void)setMargin:(ASEdgeInsets)margin { _margin.store(margin); }
|
||||
- (void)setPadding:(ASEdgeInsets)padding { _padding.store(padding); }
|
||||
- (void)setBorder:(ASEdgeInsets)border { _border.store(border); }
|
||||
- (void)setAspectRatio:(CGFloat)aspectRatio { _aspectRatio.store(aspectRatio); }
|
||||
- (void)setFlexWrap:(YGWrap)flexWrap { _flexWrap.store(flexWrap); }
|
||||
|
||||
#endif
|
||||
|
||||
#pragma mark Deprecated
|
||||
|
||||
#pragma clang diagnostic push
|
||||
|
||||
@@ -49,7 +49,9 @@ typedef NS_OPTIONS(NSUInteger, ASHierarchyState)
|
||||
/** One of the supernodes of this node is performing a transition.
|
||||
Any layout calculated during this state should not be applied immediately, but pending until later. */
|
||||
ASHierarchyStateLayoutPending = 1 << 3,
|
||||
ASHierarchyStateVisualizeLayout = 1 << 4
|
||||
ASHierarchyStateYogaLayoutEnabled = 1 << 4,
|
||||
ASHierarchyStateYogaLayoutMeasuring = 1 << 5,
|
||||
ASHierarchyStateVisualizeLayout = 1 << 6
|
||||
};
|
||||
|
||||
ASDISPLAYNODE_INLINE BOOL ASHierarchyStateIncludesLayoutPending(ASHierarchyState hierarchyState)
|
||||
@@ -62,6 +64,16 @@ ASDISPLAYNODE_INLINE BOOL ASHierarchyStateIncludesRangeManaged(ASHierarchyState
|
||||
return ((hierarchyState & ASHierarchyStateRangeManaged) == ASHierarchyStateRangeManaged);
|
||||
}
|
||||
|
||||
ASDISPLAYNODE_INLINE BOOL ASHierarchyStateIncludesYogaLayoutMeasuring(ASHierarchyState hierarchyState)
|
||||
{
|
||||
return ((hierarchyState & ASHierarchyStateYogaLayoutMeasuring) == ASHierarchyStateYogaLayoutMeasuring);
|
||||
}
|
||||
|
||||
ASDISPLAYNODE_INLINE BOOL ASHierarchyStateIncludesYogaLayoutEnabled(ASHierarchyState hierarchyState)
|
||||
{
|
||||
return ((hierarchyState & ASHierarchyStateYogaLayoutEnabled) == ASHierarchyStateYogaLayoutEnabled);
|
||||
}
|
||||
|
||||
ASDISPLAYNODE_INLINE BOOL ASHierarchyStateIncludesVisualizeLayout(ASHierarchyState hierarchyState)
|
||||
{
|
||||
return ((hierarchyState & ASHierarchyStateVisualizeLayout) == ASHierarchyStateVisualizeLayout);
|
||||
|
||||
@@ -15,14 +15,13 @@
|
||||
|
||||
#import <atomic>
|
||||
#import <AsyncDisplayKit/ASDisplayNode.h>
|
||||
#import <AsyncDisplayKit/ASThread.h>
|
||||
#import <AsyncDisplayKit/_ASTransitionContext.h>
|
||||
#import <AsyncDisplayKit/ASDisplayNode+Beta.h>
|
||||
#import <AsyncDisplayKit/ASLayoutElement.h>
|
||||
#import <AsyncDisplayKit/ASLayoutTransition.h>
|
||||
#import <AsyncDisplayKit/ASThread.h>
|
||||
#import <AsyncDisplayKit/_ASTransitionContext.h>
|
||||
#import <AsyncDisplayKit/ASWeakSet.h>
|
||||
|
||||
#import <AsyncDisplayKit/ASDisplayNode+Beta.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol _ASDisplayLayerDelegate;
|
||||
@@ -107,7 +106,7 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
|
||||
|
||||
@protected
|
||||
ASDisplayNode * __weak _supernode;
|
||||
NSMutableArray *_subnodes;
|
||||
NSMutableArray<ASDisplayNode *> *_subnodes;
|
||||
|
||||
ASLayoutElementStyle *_style;
|
||||
ASPrimitiveTraitCollection _primitiveTraitCollection;
|
||||
@@ -179,6 +178,12 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
|
||||
NSTimeInterval _layoutComputationTotalTime;
|
||||
NSInteger _layoutComputationNumberOfPasses;
|
||||
|
||||
#if YOGA
|
||||
YGNodeRef _yogaNode;
|
||||
ASDisplayNode *_yogaParent;
|
||||
NSMutableArray<ASDisplayNode *> *_yogaChildren;
|
||||
#endif
|
||||
|
||||
#if TIME_DISPLAYNODE_OPS
|
||||
@public
|
||||
NSTimeInterval _debugTimeToCreateView;
|
||||
|
||||
@@ -24,6 +24,20 @@
|
||||
#define AS_TARGET_OS_OSX (!(TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH))
|
||||
#define AS_TARGET_OS_IOS TARGET_OS_IPHONE
|
||||
|
||||
#ifndef YOGA_HEADER_PATH
|
||||
#define YOGA_HEADER_PATH <Yoga/Yoga.h>
|
||||
#endif
|
||||
|
||||
#ifndef YOGA
|
||||
#define YOGA __has_include(YOGA_HEADER_PATH)
|
||||
#endif
|
||||
|
||||
// If Yoga is available, make it available anywhere we use ASAvailability.
|
||||
// This reduces Yoga-specific code in other files.
|
||||
#if YOGA
|
||||
#import YOGA_HEADER_PATH
|
||||
#endif
|
||||
|
||||
#if AS_TARGET_OS_OSX
|
||||
|
||||
#define UIEdgeInsets NSEdgeInsets
|
||||
@@ -65,5 +79,4 @@
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,4 +2,5 @@ source 'https://github.com/CocoaPods/Specs.git'
|
||||
platform :ios, '8.0'
|
||||
target 'Sample' do
|
||||
pod 'AsyncDisplayKit', :path => '../..'
|
||||
pod 'AsyncDisplayKit/Yoga', :path => '../..'
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user