[YogaKit] support macOS, tvOS, Carthage; auto apply layout like AutoLayout. #1026
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
Pod::Spec.new do |spec|
|
Pod::Spec.new do |spec|
|
||||||
spec.name = 'Yoga'
|
spec.name = 'Yoga'
|
||||||
spec.version = '1.14.0'
|
spec.version = '1.14.1'
|
||||||
spec.license = { :type => 'MIT', :file => "LICENSE" }
|
spec.license = { :type => 'MIT', :file => "LICENSE" }
|
||||||
spec.homepage = 'https://yogalayout.com/'
|
spec.homepage = 'https://yogalayout.com/'
|
||||||
spec.documentation_url = 'https://yogalayout.com/docs'
|
spec.documentation_url = 'https://yogalayout.com/docs'
|
||||||
@@ -34,5 +34,5 @@ Pod::Spec.new do |spec|
|
|||||||
]
|
]
|
||||||
spec.source_files = 'yoga/**/*.{c,h,cpp}'
|
spec.source_files = 'yoga/**/*.{c,h,cpp}'
|
||||||
spec.public_header_files = 'yoga/{Yoga,YGEnums,YGMacros,YGNode,YGStyle,YGValue}.h'
|
spec.public_header_files = 'yoga/{Yoga,YGEnums,YGMacros,YGNode,YGStyle,YGValue}.h'
|
||||||
|
spec.static_framework = true
|
||||||
end
|
end
|
||||||
|
@@ -23,7 +23,7 @@ podspec = Pod::Spec.new do |spec|
|
|||||||
spec.ios.deployment_target = '8.0'
|
spec.ios.deployment_target = '8.0'
|
||||||
spec.ios.frameworks = 'UIKit'
|
spec.ios.frameworks = 'UIKit'
|
||||||
spec.module_name = 'YogaKit'
|
spec.module_name = 'YogaKit'
|
||||||
spec.dependency 'Yoga', '~> 1.14'
|
spec.dependency 'Yoga', '~> 1.14.1'
|
||||||
# Fixes the bug related the xcode 11 not able to find swift related frameworks.
|
# Fixes the bug related the xcode 11 not able to find swift related frameworks.
|
||||||
# https://github.com/Carthage/Carthage/issues/2825
|
# https://github.com/Carthage/Carthage/issues/2825
|
||||||
# https://twitter.com/krzyzanowskim/status/1151549874653081601?s=21
|
# https://twitter.com/krzyzanowskim/status/1151549874653081601?s=21
|
||||||
@@ -32,6 +32,7 @@ podspec = Pod::Spec.new do |spec|
|
|||||||
spec.public_header_files = 'YogaKit/Source/{YGLayout,UIView+Yoga}.h'
|
spec.public_header_files = 'YogaKit/Source/{YGLayout,UIView+Yoga}.h'
|
||||||
spec.private_header_files = 'YogaKit/Source/YGLayout+Private.h'
|
spec.private_header_files = 'YogaKit/Source/YGLayout+Private.h'
|
||||||
spec.swift_version = '5.1'
|
spec.swift_version = '5.1'
|
||||||
|
spec.static_framework = true
|
||||||
end
|
end
|
||||||
|
|
||||||
# See https://github.com/facebook/yoga/pull/366
|
# See https://github.com/facebook/yoga/pull/366
|
||||||
|
@@ -34,4 +34,9 @@ typedef void (^YGLayoutConfigurationBlock)(YGLayout* layout);
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@interface UIView (YogaKitAutoApplyLayout)
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
NS_ASSUME_NONNULL_END
|
||||||
|
@@ -35,3 +35,88 @@ static const void* kYGYogaAssociatedKey = &kYGYogaAssociatedKey;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
static const void* kYGBoundsSizeAssociatedKey = &kYGBoundsSizeAssociatedKey;
|
||||||
|
static void YogaSwizzleInstanceMethod(Class cls, SEL originalSelector, SEL swizzledSelector);
|
||||||
|
|
||||||
|
@implementation UIView (YogaKitAutoApplyLayout)
|
||||||
|
|
||||||
|
+ (void)load {
|
||||||
|
static dispatch_once_t onceToken = 0;
|
||||||
|
dispatch_once(&onceToken, ^{
|
||||||
|
YogaSwizzleInstanceMethod(self, @selector(initWithFrame:), @selector(_yoga_initWithFrame:));
|
||||||
|
YogaSwizzleInstanceMethod(self, @selector(setFrame:), @selector(_yoga_setFrame:));
|
||||||
|
YogaSwizzleInstanceMethod(self, @selector(setBounds:), @selector(_yoga_setBounds:));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGSize)_yoga_boundsSize {
|
||||||
|
NSValue *value = (NSValue *)objc_getAssociatedObject(self, kYGBoundsSizeAssociatedKey);
|
||||||
|
|
||||||
|
return value ? value.CGSizeValue : CGSizeMake(YGUndefined, YGUndefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)set_yoga_boundsSize:(CGSize)size {
|
||||||
|
objc_setAssociatedObject(self,
|
||||||
|
kYGBoundsSizeAssociatedKey,
|
||||||
|
[NSValue valueWithCGSize:size],
|
||||||
|
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (instancetype)_yoga_initWithFrame:(CGRect)frame {
|
||||||
|
id _self = [self _yoga_initWithFrame:frame];
|
||||||
|
if (_self) {
|
||||||
|
[self _yoga_applyLayout];
|
||||||
|
}
|
||||||
|
|
||||||
|
return _self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_yoga_setFrame:(CGRect)frame {
|
||||||
|
[self _yoga_setFrame:frame];
|
||||||
|
|
||||||
|
[self _yoga_applyLayout];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_yoga_setBounds:(CGRect)bounds {
|
||||||
|
[self _yoga_setBounds:bounds];
|
||||||
|
|
||||||
|
[self _yoga_applyLayout];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)_yoga_applyLayout {
|
||||||
|
if (self.isYogaEnabled && self.yoga.isEnabled) {
|
||||||
|
CGSize size = self.bounds.size;
|
||||||
|
CGSize prev = self._yoga_boundsSize;
|
||||||
|
if (!CGSizeEqualToSize(size, prev)) {
|
||||||
|
self._yoga_boundsSize = size;
|
||||||
|
[self.yoga applyLayoutPreservingOrigin:YES];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
static void YogaSwizzleInstanceMethod(Class cls, SEL originalSelector, SEL swizzledSelector) {
|
||||||
|
if (!cls || !originalSelector || !swizzledSelector) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Method originalMethod = class_getInstanceMethod(cls, originalSelector);
|
||||||
|
Method swizzledMethod = class_getInstanceMethod(cls, swizzledSelector);
|
||||||
|
if (!originalMethod || !swizzledMethod) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMP swizzledIMP = method_getImplementation(swizzledMethod);
|
||||||
|
if (class_addMethod(cls, originalSelector, swizzledIMP, method_getTypeEncoding(swizzledMethod))) {
|
||||||
|
class_replaceMethod(cls,
|
||||||
|
swizzledSelector,
|
||||||
|
method_getImplementation(originalMethod),
|
||||||
|
method_getTypeEncoding(originalMethod));
|
||||||
|
} else {
|
||||||
|
method_exchangeImplementations(originalMethod, swizzledMethod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -162,6 +162,7 @@ static YGConfigRef globalConfig;
|
|||||||
|
|
||||||
@property(nonatomic, weak, readonly) UIView* view;
|
@property(nonatomic, weak, readonly) UIView* view;
|
||||||
@property(nonatomic, assign, readonly) BOOL isUIView;
|
@property(nonatomic, assign, readonly) BOOL isUIView;
|
||||||
|
@property(nonatomic, assign) BOOL isApplingLayout;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@@ -292,11 +293,19 @@ YG_PROPERTY(CGFloat, aspectRatio, AspectRatio)
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)applyLayout {
|
- (void)applyLayout {
|
||||||
|
if (self.isApplingLayout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
[self calculateLayoutWithSize:self.view.bounds.size];
|
[self calculateLayoutWithSize:self.view.bounds.size];
|
||||||
YGApplyLayoutToViewHierarchy(self.view, NO);
|
YGApplyLayoutToViewHierarchy(self.view, NO);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin {
|
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin {
|
||||||
|
if (self.isApplingLayout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
[self calculateLayoutWithSize:self.view.bounds.size];
|
[self calculateLayoutWithSize:self.view.bounds.size];
|
||||||
YGApplyLayoutToViewHierarchy(self.view, preserveOrigin);
|
YGApplyLayoutToViewHierarchy(self.view, preserveOrigin);
|
||||||
}
|
}
|
||||||
@@ -304,6 +313,10 @@ YG_PROPERTY(CGFloat, aspectRatio, AspectRatio)
|
|||||||
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin
|
- (void)applyLayoutPreservingOrigin:(BOOL)preserveOrigin
|
||||||
dimensionFlexibility:
|
dimensionFlexibility:
|
||||||
(YGDimensionFlexibility)dimensionFlexibility {
|
(YGDimensionFlexibility)dimensionFlexibility {
|
||||||
|
if (self.isApplingLayout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CGSize size = self.view.bounds.size;
|
CGSize size = self.view.bounds.size;
|
||||||
if (dimensionFlexibility & YGDimensionFlexibilityFlexibleWidth) {
|
if (dimensionFlexibility & YGDimensionFlexibilityFlexibleWidth) {
|
||||||
size.width = YGUndefined;
|
size.width = YGUndefined;
|
||||||
@@ -463,12 +476,22 @@ static void YGApplyLayoutToViewHierarchy(UIView* view, BOOL preserveOrigin) {
|
|||||||
[NSThread isMainThread],
|
[NSThread isMainThread],
|
||||||
@"Framesetting should only be done on the main thread.");
|
@"Framesetting should only be done on the main thread.");
|
||||||
|
|
||||||
|
if (!view.isYogaEnabled || !view.yoga.isEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const YGLayout* yoga = view.yoga;
|
const YGLayout* yoga = view.yoga;
|
||||||
|
|
||||||
|
if (yoga.isApplingLayout) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!yoga.isIncludedInLayout) {
|
if (!yoga.isIncludedInLayout) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
yoga.isApplingLayout = YES;
|
||||||
|
|
||||||
YGNodeRef node = yoga.node;
|
YGNodeRef node = yoga.node;
|
||||||
const CGPoint topLeft = {
|
const CGPoint topLeft = {
|
||||||
YGNodeLayoutGetLeft(node),
|
YGNodeLayoutGetLeft(node),
|
||||||
@@ -481,7 +504,7 @@ static void YGApplyLayoutToViewHierarchy(UIView* view, BOOL preserveOrigin) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const CGPoint origin = preserveOrigin ? view.frame.origin : CGPointZero;
|
const CGPoint origin = preserveOrigin ? view.frame.origin : CGPointZero;
|
||||||
view.frame = (CGRect){
|
CGRect frame = (CGRect){
|
||||||
.origin =
|
.origin =
|
||||||
{
|
{
|
||||||
.x = YGRoundPixelValue(topLeft.x + origin.x),
|
.x = YGRoundPixelValue(topLeft.x + origin.x),
|
||||||
@@ -489,18 +512,31 @@ static void YGApplyLayoutToViewHierarchy(UIView* view, BOOL preserveOrigin) {
|
|||||||
},
|
},
|
||||||
.size =
|
.size =
|
||||||
{
|
{
|
||||||
.width = YGRoundPixelValue(bottomRight.x) -
|
.width = MAX(YGRoundPixelValue(bottomRight.x) -
|
||||||
YGRoundPixelValue(topLeft.x),
|
YGRoundPixelValue(topLeft.x), 0),
|
||||||
.height = YGRoundPixelValue(bottomRight.y) -
|
.height = MAX(YGRoundPixelValue(bottomRight.y) -
|
||||||
YGRoundPixelValue(topLeft.y),
|
YGRoundPixelValue(topLeft.y), 0),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// use bounds/center and not frame if non-identity transform.
|
||||||
|
view.bounds = (CGRect) {
|
||||||
|
.origin = view.bounds.origin,
|
||||||
|
.size = frame.size
|
||||||
|
};
|
||||||
|
|
||||||
|
view.center = (CGPoint) {
|
||||||
|
.x = YGRoundPixelValue(CGRectGetMinX(frame) + CGRectGetWidth(frame) * 0.5),
|
||||||
|
.y = YGRoundPixelValue(CGRectGetMinY(frame) + CGRectGetHeight(frame) * 0.5)
|
||||||
|
};
|
||||||
|
|
||||||
if (!yoga.isLeaf) {
|
if (!yoga.isLeaf) {
|
||||||
for (NSUInteger i = 0; i < view.subviews.count; i++) {
|
for (NSUInteger i = 0; i < view.subviews.count; i++) {
|
||||||
YGApplyLayoutToViewHierarchy(view.subviews[i], NO);
|
YGApplyLayoutToViewHierarchy(view.subviews[i], NO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
yoga.isApplingLayout = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@@ -1,6 +1,8 @@
|
|||||||
|
platform :ios, '9.0'
|
||||||
use_frameworks!
|
use_frameworks!
|
||||||
|
|
||||||
target 'YogaKitSample' do
|
target 'YogaKitSample' do
|
||||||
|
pod 'Yoga', :path => '../../Yoga.podspec'
|
||||||
pod 'YogaKit', :path => '../../YogaKit.podspec'
|
pod 'YogaKit', :path => '../../YogaKit.podspec'
|
||||||
pod 'IGListKit', '~> 2.1.0'
|
pod 'IGListKit', '~> 4.0.0'
|
||||||
end
|
end
|
||||||
|
@@ -1,26 +1,33 @@
|
|||||||
PODS:
|
PODS:
|
||||||
- IGListKit (2.1.0):
|
- IGListDiffKit (4.0.0)
|
||||||
- IGListKit/Default (= 2.1.0)
|
- IGListKit (4.0.0):
|
||||||
- IGListKit/Default (2.1.0):
|
- IGListDiffKit (= 4.0.0)
|
||||||
- IGListKit/Diffing
|
- Yoga (1.14.1)
|
||||||
- IGListKit/Diffing (2.1.0)
|
- YogaKit (1.18.1):
|
||||||
- Yoga (1.7.0)
|
- Yoga (~> 1.14.1)
|
||||||
- YogaKit (1.7.0):
|
|
||||||
- Yoga (~> 1.7)
|
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- IGListKit (~> 2.1.0)
|
- IGListKit (~> 4.0.0)
|
||||||
|
- Yoga (from `../../Yoga.podspec`)
|
||||||
- YogaKit (from `../../YogaKit.podspec`)
|
- YogaKit (from `../../YogaKit.podspec`)
|
||||||
|
|
||||||
|
SPEC REPOS:
|
||||||
|
trunk:
|
||||||
|
- IGListDiffKit
|
||||||
|
- IGListKit
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
|
Yoga:
|
||||||
|
:path: "../../Yoga.podspec"
|
||||||
YogaKit:
|
YogaKit:
|
||||||
:path: ../../YogaKit.podspec
|
:path: "../../YogaKit.podspec"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
IGListKit: b826c68ef7a4ae1626c09d4d3e1ea7a169e6c36e
|
IGListDiffKit: 665d6cf43ce726e676013db9c7d6c4294259b6b2
|
||||||
Yoga: 2ed1d7accfef3610a67f58c0cf101a0662137f2c
|
IGListKit: fd5a5d21935298f5849fa49d426843cff97b77c7
|
||||||
YogaKit: 31576530e8fcae3175469719ec3212397403330b
|
Yoga: 1b62f19e549f5e174fc935ba76a47a8d9b60211e
|
||||||
|
YogaKit: befe87ed72becf4125f290a33af021e9992712c7
|
||||||
|
|
||||||
PODFILE CHECKSUM: 216f8e7127767709e0e43f3711208d238fa5c404
|
PODFILE CHECKSUM: 31f0f3ccdee77adc2f4b58b4772186c206fd1446
|
||||||
|
|
||||||
COCOAPODS: 1.1.1
|
COCOAPODS: 1.9.1
|
||||||
|
@@ -1,10 +1,3 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
||||||
*
|
|
||||||
* This source code is licensed under the MIT license found in the
|
|
||||||
* LICENSE file in the root directory of this source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// !$*UTF8*$!
|
// !$*UTF8*$!
|
||||||
{
|
{
|
||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
@@ -178,7 +171,6 @@
|
|||||||
13687D401DF8748300E7C260 /* Frameworks */,
|
13687D401DF8748300E7C260 /* Frameworks */,
|
||||||
13687D411DF8748300E7C260 /* Resources */,
|
13687D411DF8748300E7C260 /* Resources */,
|
||||||
FA2FB9DD6471BDD3FBCE503B /* [CP] Embed Pods Frameworks */,
|
FA2FB9DD6471BDD3FBCE503B /* [CP] Embed Pods Frameworks */,
|
||||||
6E01EB987F1564F3D71EBE5A /* [CP] Copy Pods Resources */,
|
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
@@ -233,6 +225,7 @@
|
|||||||
developmentRegion = English;
|
developmentRegion = English;
|
||||||
hasScannedForEncodings = 0;
|
hasScannedForEncodings = 0;
|
||||||
knownRegions = (
|
knownRegions = (
|
||||||
|
English,
|
||||||
en,
|
en,
|
||||||
Base,
|
Base,
|
||||||
);
|
);
|
||||||
@@ -272,28 +265,16 @@
|
|||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
);
|
);
|
||||||
name = "[CP] Check Pods Manifest.lock";
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-YogaKitSample-checkManifestLockResult.txt",
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
showEnvVarsInLog = 0;
|
|
||||||
};
|
|
||||||
6E01EB987F1564F3D71EBE5A /* [CP] Copy Pods Resources */ = {
|
|
||||||
isa = PBXShellScriptBuildPhase;
|
|
||||||
buildActionMask = 2147483647;
|
|
||||||
files = (
|
|
||||||
);
|
|
||||||
inputPaths = (
|
|
||||||
);
|
|
||||||
name = "[CP] Copy Pods Resources";
|
|
||||||
outputPaths = (
|
|
||||||
);
|
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
|
||||||
shellPath = /bin/sh;
|
|
||||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-YogaKitSample/Pods-YogaKitSample-resources.sh\"\n";
|
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
FA2FB9DD6471BDD3FBCE503B /* [CP] Embed Pods Frameworks */ = {
|
FA2FB9DD6471BDD3FBCE503B /* [CP] Embed Pods Frameworks */ = {
|
||||||
@@ -302,13 +283,18 @@
|
|||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-YogaKitSample/Pods-YogaKitSample-frameworks.sh",
|
||||||
|
"${BUILT_PRODUCTS_DIR}/IGListDiffKit/IGListDiffKit.framework",
|
||||||
|
"${BUILT_PRODUCTS_DIR}/IGListKit/IGListKit.framework",
|
||||||
);
|
);
|
||||||
name = "[CP] Embed Pods Frameworks";
|
name = "[CP] Embed Pods Frameworks";
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/IGListDiffKit.framework",
|
||||||
|
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/IGListKit.framework",
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-YogaKitSample/Pods-YogaKitSample-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-YogaKitSample/Pods-YogaKitSample-frameworks.sh\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
@@ -446,7 +432,7 @@
|
|||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_INSTALL_OBJC_HEADER = NO;
|
SWIFT_INSTALL_OBJC_HEADER = NO;
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 3.0;
|
SWIFT_VERSION = 5.0;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
@@ -461,7 +447,7 @@
|
|||||||
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.YogaKitSample;
|
PRODUCT_BUNDLE_IDENTIFIER = com.facebook.YogaKitSample;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_INSTALL_OBJC_HEADER = NO;
|
SWIFT_INSTALL_OBJC_HEADER = NO;
|
||||||
SWIFT_VERSION = 3.0;
|
SWIFT_VERSION = 5.0;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
|
@@ -18,12 +18,12 @@ private final class ExampleModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ExampleModel: IGListDiffable {
|
extension ExampleModel: ListDiffable {
|
||||||
fileprivate func diffIdentifier() -> NSObjectProtocol {
|
fileprivate func diffIdentifier() -> NSObjectProtocol {
|
||||||
return title as NSString
|
return title as NSString
|
||||||
}
|
}
|
||||||
|
|
||||||
fileprivate func isEqual(toDiffableObject object: IGListDiffable?) -> Bool {
|
fileprivate func isEqual(toDiffableObject object: ListDiffable?) -> Bool {
|
||||||
guard let otherObj = object as? ExampleModel else { return false }
|
guard let otherObj = object as? ExampleModel else { return false }
|
||||||
|
|
||||||
return (title == otherObj.title) &&
|
return (title == otherObj.title) &&
|
||||||
@@ -31,11 +31,11 @@ extension ExampleModel: IGListDiffable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final class ExamplesViewController: UIViewController, IGListAdapterDataSource, IGListSingleSectionControllerDelegate {
|
final class ExamplesViewController: UIViewController, ListAdapterDataSource, ListSingleSectionControllerDelegate {
|
||||||
private lazy var adapter: IGListAdapter = {
|
private lazy var adapter: ListAdapter = {
|
||||||
return IGListAdapter(updater: IGListAdapterUpdater(), viewController: self, workingRangeSize: 0)
|
return ListAdapter(updater: ListAdapterUpdater(), viewController: self, workingRangeSize: 0)
|
||||||
}()
|
}()
|
||||||
private let collectionView = IGListCollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
|
private let collectionView = ListCollectionView(frame: .zero)
|
||||||
|
|
||||||
|
|
||||||
// Update this to array to create more examples.
|
// Update this to array to create more examples.
|
||||||
@@ -47,6 +47,7 @@ final class ExamplesViewController: UIViewController, IGListAdapterDataSource, I
|
|||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
title = "Examples"
|
title = "Examples"
|
||||||
|
collectionView.backgroundColor = .clear
|
||||||
view.addSubview(collectionView)
|
view.addSubview(collectionView)
|
||||||
adapter.collectionView = collectionView
|
adapter.collectionView = collectionView
|
||||||
adapter.dataSource = self
|
adapter.dataSource = self
|
||||||
@@ -59,16 +60,16 @@ final class ExamplesViewController: UIViewController, IGListAdapterDataSource, I
|
|||||||
|
|
||||||
//MARK: IGListAdapterDataSource
|
//MARK: IGListAdapterDataSource
|
||||||
|
|
||||||
func objects(for listAdapter: IGListAdapter) -> [IGListDiffable] {
|
func objects(for listAdapter: ListAdapter) -> [ListDiffable] {
|
||||||
return models as [IGListDiffable]
|
return models as [ListDiffable]
|
||||||
}
|
}
|
||||||
|
|
||||||
func listAdapter(_ listAdapter: IGListAdapter, sectionControllerFor object: Any) -> IGListSectionController {
|
func listAdapter(_ listAdapter: ListAdapter, sectionControllerFor object: Any) -> ListSectionController {
|
||||||
let sizeBlock: IGListSingleSectionCellSizeBlock = { (model, context) in
|
let sizeBlock: ListSingleSectionCellSizeBlock = { (model, context) in
|
||||||
return CGSize(width: (context?.containerSize.width)!, height: 75.0)
|
return CGSize(width: (context?.containerSize.width)!, height: 75.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
let configureBlock: IGListSingleSectionCellConfigureBlock = { (model, cell) in
|
let configureBlock: ListSingleSectionCellConfigureBlock = { (model, cell) in
|
||||||
guard let m = model as? ExampleModel, let c = cell as? SingleLabelCollectionCell else {
|
guard let m = model as? ExampleModel, let c = cell as? SingleLabelCollectionCell else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -76,18 +77,18 @@ final class ExamplesViewController: UIViewController, IGListAdapterDataSource, I
|
|||||||
c.label.text = m.title
|
c.label.text = m.title
|
||||||
}
|
}
|
||||||
|
|
||||||
let sectionController = IGListSingleSectionController(cellClass: SingleLabelCollectionCell.self,
|
let sectionController = ListSingleSectionController(cellClass: SingleLabelCollectionCell.self,
|
||||||
configureBlock: configureBlock,
|
configureBlock: configureBlock,
|
||||||
sizeBlock: sizeBlock)
|
sizeBlock: sizeBlock)
|
||||||
sectionController.selectionDelegate = self
|
sectionController.selectionDelegate = self
|
||||||
return sectionController
|
return sectionController
|
||||||
}
|
}
|
||||||
|
|
||||||
func emptyView(for listAdapter: IGListAdapter) -> UIView? { return nil }
|
func emptyView(for listAdapter: ListAdapter) -> UIView? { return nil }
|
||||||
|
|
||||||
//MARK: IGListSingleSectionControllerDelegate
|
//MARK: IGListSingleSectionControllerDelegate
|
||||||
|
|
||||||
func didSelect(_ sectionController: IGListSingleSectionController) {
|
func didSelect(_ sectionController: ListSingleSectionController, with object: Any) {
|
||||||
let section = adapter.section(for: sectionController)
|
let section = adapter.section(for: sectionController)
|
||||||
let model = models[section]
|
let model = models[section]
|
||||||
|
|
||||||
|
@@ -32,5 +32,7 @@
|
|||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
</array>
|
</array>
|
||||||
|
<key>UIUserInterfaceStyle</key>
|
||||||
|
<string>Light</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
@@ -32,22 +32,24 @@ final class BasicViewController: UIViewController {
|
|||||||
}
|
}
|
||||||
root.addSubview(child1)
|
root.addSubview(child1)
|
||||||
|
|
||||||
let child2 = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
|
let child2 = UIView()
|
||||||
child2.backgroundColor = .green
|
child2.backgroundColor = .green
|
||||||
child2.configureLayout { (layout) in
|
child2.configureLayout { (layout) in
|
||||||
layout.isEnabled = true
|
layout.isEnabled = true
|
||||||
layout.alignSelf = .flexEnd
|
layout.alignSelf = .flexEnd
|
||||||
|
layout.width = 200
|
||||||
|
layout.height = 200
|
||||||
}
|
}
|
||||||
root.addSubview(child2)
|
root.addSubview(child2)
|
||||||
|
|
||||||
let child3 = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
|
let child3 = UIView()
|
||||||
child3.backgroundColor = .yellow
|
child3.backgroundColor = .yellow
|
||||||
child3.configureLayout { (layout) in
|
child3.configureLayout { (layout) in
|
||||||
layout.isEnabled = true
|
layout.isEnabled = true
|
||||||
layout.alignSelf = .flexStart
|
layout.alignSelf = .flexStart
|
||||||
|
layout.width = 100
|
||||||
|
layout.height = 100
|
||||||
}
|
}
|
||||||
root.addSubview(child3)
|
root.addSubview(child3)
|
||||||
|
|
||||||
root.yoga.applyLayout(preservingOrigin: true)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -51,9 +51,9 @@ final class LayoutInclusionViewController: UIViewController {
|
|||||||
}
|
}
|
||||||
contentView.addSubview(disappearingView)
|
contentView.addSubview(disappearingView)
|
||||||
|
|
||||||
button.setTitle("Add Blue View", for: UIControlState.selected)
|
button.setTitle("Add Blue View", for: .selected)
|
||||||
button.setTitle("Remove Blue View", for: UIControlState.normal)
|
button.setTitle("Remove Blue View", for: .normal)
|
||||||
button.addTarget(self, action: #selector(buttonWasTapped), for: UIControlEvents.touchUpInside)
|
button.addTarget(self, action: #selector(buttonWasTapped), for: UIControl.Event.touchUpInside)
|
||||||
button.configureLayout { (layout) in
|
button.configureLayout { (layout) in
|
||||||
layout.isEnabled = true
|
layout.isEnabled = true
|
||||||
layout.height = 300
|
layout.height = 300
|
||||||
@@ -61,12 +61,10 @@ final class LayoutInclusionViewController: UIViewController {
|
|||||||
layout.alignSelf = .center
|
layout.alignSelf = .center
|
||||||
}
|
}
|
||||||
root.addSubview(button)
|
root.addSubview(button)
|
||||||
|
|
||||||
root.yoga.applyLayout(preservingOrigin: false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK - UIButton Action
|
// MARK - UIButton Action
|
||||||
func buttonWasTapped() {
|
@objc func buttonWasTapped() {
|
||||||
button.isSelected = !button.isSelected
|
button.isSelected = !button.isSelected
|
||||||
|
|
||||||
button.isUserInteractionEnabled = false
|
button.isUserInteractionEnabled = false
|
||||||
|
@@ -42,7 +42,6 @@ final class SingleLabelCollectionCell: UICollectionViewCell {
|
|||||||
override func layoutSubviews() {
|
override func layoutSubviews() {
|
||||||
super.layoutSubviews()
|
super.layoutSubviews()
|
||||||
|
|
||||||
contentView.yoga.applyLayout(preservingOrigin: false)
|
|
||||||
label.frame = contentView.bounds
|
label.frame = contentView.bounds
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user