diff --git a/YogaKit/CHANGELOG.md b/YogaKit/CHANGELOG.md index 58f41d9b..c6b42a3a 100644 --- a/YogaKit/CHANGELOG.md +++ b/YogaKit/CHANGELOG.md @@ -42,3 +42,5 @@ view.configureLayout { (layout) in layout.height = 50 } ``` + +- Added new `isDirty` property, and make `markDirty` a little more performant. diff --git a/YogaKit/Source/YGLayout.h b/YogaKit/Source/YGLayout.h index e9f49b12..70a4b015 100644 --- a/YogaKit/Source/YGLayout.h +++ b/YogaKit/Source/YGLayout.h @@ -111,6 +111,12 @@ */ @property (nonatomic, readonly, assign) BOOL isLeaf; +/** + Return's a BOOL indicating if a view is dirty. When a node is dirty + it usually indicates that it will be remeasured on the next layout pass. + */ +@property (nonatomic, readonly, assign) BOOL isDirty; + /** Mark that a view's layout needs to be recalculated. Only works for leaf views. */ diff --git a/YogaKit/Source/YGLayout.m b/YogaKit/Source/YGLayout.m index d7240a8b..cd62f51a 100644 --- a/YogaKit/Source/YGLayout.m +++ b/YogaKit/Source/YGLayout.m @@ -120,11 +120,26 @@ YG_VALUE_EDGE_PROPERTY(lowercased_name, capitalized_name, capitalized_name, YGEd YGNodeFree(self.node); } +- (BOOL)isDirty +{ + return YGNodeIsDirty(self.node); +} + - (void)markDirty { - if (self.isLeaf) { - YGNodeMarkDirty(self.node); + if (self.isDirty || !self.isLeaf) { + return; } + + // Yoga is not happy if we try to mark a node as "dirty" before we have set + // the measure function. Since we already know that this is a leaf, + // this *should* be fine. Forgive me Hack Gods. + const YGNodeRef node = self.node; + if (YGNodeGetMeasureFunc(node) == NULL) { + YGNodeSetMeasureFunc(node, YGMeasureView); + } + + YGNodeMarkDirty(node); } - (NSUInteger)numberOfChildren diff --git a/YogaKit/Tests/YogaKitTests.m b/YogaKit/Tests/YogaKitTests.m index 5a1d56f1..dca193c4 100644 --- a/YogaKit/Tests/YogaKitTests.m +++ b/YogaKit/Tests/YogaKitTests.m @@ -153,6 +153,24 @@ XCTAssertEqual(25, view2.frame.origin.y); } +- (void)testMarkingDirtyOnlyWorksOnLeafNodes +{ + UIView *container = [[UIView alloc] initWithFrame:CGRectZero]; + container.yoga.isEnabled = YES; + + UIView *subview = [[UIView alloc] initWithFrame:CGRectZero]; + subview.yoga.isEnabled = YES; + [container addSubview:subview]; + + XCTAssertFalse(container.yoga.isDirty); + [container.yoga markDirty]; + XCTAssertFalse(container.yoga.isDirty); + + XCTAssertFalse(subview.yoga.isDirty); + [subview.yoga markDirty]; + XCTAssertTrue(subview.yoga.isDirty); +} + - (void)testThatMarkingLeafsAsDirtyWillTriggerASizeRecalculation { UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 500, 50)];