Add locking for ASInterfaceState. Misc. cleanup.

This commit is contained in:
Scott Goodson 2015-11-29 14:57:43 -08:00
parent fb9f37b293
commit 254f55b758
5 changed files with 68 additions and 65 deletions

View File

@ -379,11 +379,6 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
return YES;
}
- (void)__exitedHierarchy
{
}
- (UIView *)_viewToLoad
{
UIView *view;
@ -787,55 +782,9 @@ static ASDisplayNodeMethodOverrides GetASDisplayNodeMethodOverrides(Class c)
return transform;
}
static inline BOOL _ASDisplayNodeIsAncestorOfDisplayNode(ASDisplayNode *possibleAncestor, ASDisplayNode *possibleDescendent)
{
ASDisplayNode *supernode = possibleDescendent;
while (supernode) {
if (supernode == possibleAncestor) {
return YES;
}
supernode = supernode.supernode;
}
return NO;
}
/**
* NOTE: It is an error to try to convert between nodes which do not share a common ancestor. This behavior is
* disallowed in UIKit documentation and the behavior is left undefined. The output does not have a rigorously defined
* failure mode (i.e. returning CGPointZero or returning the point exactly as passed in). Rather than track the internal
* undefined and undocumented behavior of UIKit in ASDisplayNode, this operation is defined to be incorrect in all
* circumstances and must be fixed wherever encountered.
*/
static inline ASDisplayNode *_ASDisplayNodeFindClosestCommonAncestor(ASDisplayNode *node1, ASDisplayNode *node2)
{
ASDisplayNode *possibleAncestor = node1;
while (possibleAncestor) {
if (_ASDisplayNodeIsAncestorOfDisplayNode(possibleAncestor, node2)) {
break;
}
possibleAncestor = possibleAncestor.supernode;
}
ASDisplayNodeCAssertNotNil(possibleAncestor, @"Could not find a common ancestor between node1: %@ and node2: %@", node1, node2);
return possibleAncestor;
}
static inline ASDisplayNode *_getRootNode(ASDisplayNode *node)
{
// node <- supernode on each loop
// previous <- node on each loop where node is not nil
// previous is the final non-nil value of supernode, i.e. the root node
ASDisplayNode *previousNode = node;
while ((node = [node supernode])) {
previousNode = node;
}
return previousNode;
}
static inline CATransform3D _calculateTransformFromReferenceToTarget(ASDisplayNode *referenceNode, ASDisplayNode *targetNode)
{
ASDisplayNode *ancestor = _ASDisplayNodeFindClosestCommonAncestor(referenceNode, targetNode);
ASDisplayNode *ancestor = ASDisplayNodeFindClosestCommonAncestor(referenceNode, targetNode);
// Transform into global (away from reference coordinate space)
CATransform3D transformToGlobal = [referenceNode _transformToAncestor:ancestor];
@ -850,7 +799,7 @@ static inline CATransform3D _calculateTransformFromReferenceToTarget(ASDisplayNo
{
ASDisplayNodeAssertThreadAffinity(self);
// Get root node of the accessible node hierarchy, if node not specified
node = node ? node : _getRootNode(self);
node = node ? node : ASDisplayNodeUltimateParentOfNode(self);
// Calculate transform to map points between coordinate spaces
CATransform3D nodeTransform = _calculateTransformFromReferenceToTarget(node, self);
@ -865,7 +814,7 @@ static inline CATransform3D _calculateTransformFromReferenceToTarget(ASDisplayNo
{
ASDisplayNodeAssertThreadAffinity(self);
// Get root node of the accessible node hierarchy, if node not specified
node = node ? node : _getRootNode(self);
node = node ? node : ASDisplayNodeUltimateParentOfNode(self);
// Calculate transform to map points between coordinate spaces
CATransform3D nodeTransform = _calculateTransformFromReferenceToTarget(self, node);
@ -880,7 +829,7 @@ static inline CATransform3D _calculateTransformFromReferenceToTarget(ASDisplayNo
{
ASDisplayNodeAssertThreadAffinity(self);
// Get root node of the accessible node hierarchy, if node not specified
node = node ? node : _getRootNode(self);
node = node ? node : ASDisplayNodeUltimateParentOfNode(self);
// Calculate transform to map points between coordinate spaces
CATransform3D nodeTransform = _calculateTransformFromReferenceToTarget(node, self);
@ -895,7 +844,7 @@ static inline CATransform3D _calculateTransformFromReferenceToTarget(ASDisplayNo
{
ASDisplayNodeAssertThreadAffinity(self);
// Get root node of the accessible node hierarchy, if node not specified
node = node ? node : _getRootNode(self);
node = node ? node : ASDisplayNodeUltimateParentOfNode(self);
// Calculate transform to map points between coordinate spaces
CATransform3D nodeTransform = _calculateTransformFromReferenceToTarget(self, node);
@ -1614,6 +1563,7 @@ void recursivelyEnsureDisplayForLayer(CALayer *layer)
- (void)__didLoad
{
ASDN::MutexLocker l(_propertyLock);
if (_nodeLoadedBlock) {
_nodeLoadedBlock(self);
_nodeLoadedBlock = nil;
@ -1638,8 +1588,6 @@ void recursivelyEnsureDisplayForLayer(CALayer *layer)
ASDisplayNodeAssertMainThread();
ASDisplayNodeAssert(_flags.isExitingHierarchy, @"You should never call -didExitHierarchy directly. Appearance is automatically managed by ASDisplayNode");
ASDisplayNodeAssert(!_flags.isEnteringHierarchy, @"ASDisplayNode inconsistency. __enterHierarchy and __exitHierarchy are mutually exclusive");
[self __exitedHierarchy];
}
- (void)clearContents
@ -1689,11 +1637,13 @@ void recursivelyEnsureDisplayForLayer(CALayer *layer)
- (ASInterfaceState)interfaceState
{
ASDN::MutexLocker l(_propertyLock);
return _interfaceState;
}
- (void)setInterfaceState:(ASInterfaceState)interfaceState
{
ASDN::MutexLocker l(_propertyLock);
if (interfaceState != _interfaceState) {
if ((interfaceState & ASInterfaceStateMeasureLayout) != (_interfaceState & ASInterfaceStateMeasureLayout)) {
// Trigger asynchronous measurement if it is not already cached or being calculated.

View File

@ -24,13 +24,18 @@ extern ASDisplayNode *ASLayerToDisplayNode(CALayer *layer);
*/
extern ASDisplayNode *ASViewToDisplayNode(UIView *view);
/**
Given a node, returns the root of the node heirarchy (where supernode == nil)
*/
extern ASDisplayNode *ASDisplayNodeUltimateParentOfNode(ASDisplayNode *node);
/**
This function will walk the layer heirarchy, spanning discontinuous sections of the node heirarchy (e.g. the layers
of UIKit intermediate views in UIViewControllers, UITableView, UICollectionView).
In the event that a node's backing layer is not created yet, the function will only walk the direct subnodes instead
of forcing the layer heirarchy to be created.
*/
void ASDisplayNodePerformBlockOnEveryNode(CALayer *layer, ASDisplayNode *node, void(^block)(ASDisplayNode *node));
extern void ASDisplayNodePerformBlockOnEveryNode(CALayer *layer, ASDisplayNode *node, void(^block)(ASDisplayNode *node));
/**
Given a display node, traverses up the layer tree hierarchy, returning the first display node that passes block.
@ -42,6 +47,16 @@ extern id ASDisplayNodeFind(ASDisplayNode *node, BOOL (^block)(ASDisplayNode *no
*/
extern id ASDisplayNodeFindClass(ASDisplayNode *start, Class c);
/**
* Given two nodes, finds their most immediate common parent. Used for geometry conversion methods.
* NOTE: It is an error to try to convert between nodes which do not share a common ancestor. This behavior is
* disallowed in UIKit documentation and the behavior is left undefined. The output does not have a rigorously defined
* failure mode (i.e. returning CGPointZero or returning the point exactly as passed in). Rather than track the internal
* undefined and undocumented behavior of UIKit in ASDisplayNode, this operation is defined to be incorrect in all
* circumstances and must be fixed wherever encountered.
*/
extern ASDisplayNode *ASDisplayNodeFindClosestCommonAncestor(ASDisplayNode *node1, ASDisplayNode *node2);
/**
Given a display node, collects all descendents. This is a specialization of ASCollectContainer() that walks the Core Animation layer tree as opposed to the display node tree, thus supporting non-continues display node hierarchies.
*/

View File

@ -10,17 +10,17 @@
#import "ASDisplayNodeInternal.h"
inline ASDisplayNode *ASLayerToDisplayNode(CALayer *layer)
extern ASDisplayNode *ASLayerToDisplayNode(CALayer *layer)
{
return layer.asyncdisplaykit_node;
}
inline ASDisplayNode *ASViewToDisplayNode(UIView *view)
extern ASDisplayNode *ASViewToDisplayNode(UIView *view)
{
return view.asyncdisplaykit_node;
}
void ASDisplayNodePerformBlockOnEveryNode(CALayer *layer, ASDisplayNode *node, void(^block)(ASDisplayNode *node))
extern void ASDisplayNodePerformBlockOnEveryNode(CALayer *layer, ASDisplayNode *node, void(^block)(ASDisplayNode *node))
{
if (!node) {
ASDisplayNodeCAssertNotNil(layer, @"Cannot recursively perform with nil node and nil layer");
@ -148,6 +148,45 @@ extern id ASDisplayNodeFindFirstSubnodeOfClass(ASDisplayNode *start, Class c)
});
}
static inline BOOL _ASDisplayNodeIsAncestorOfDisplayNode(ASDisplayNode *possibleAncestor, ASDisplayNode *possibleDescendent)
{
ASDisplayNode *supernode = possibleDescendent;
while (supernode) {
if (supernode == possibleAncestor) {
return YES;
}
supernode = supernode.supernode;
}
return NO;
}
extern ASDisplayNode *ASDisplayNodeFindClosestCommonAncestor(ASDisplayNode *node1, ASDisplayNode *node2)
{
ASDisplayNode *possibleAncestor = node1;
while (possibleAncestor) {
if (_ASDisplayNodeIsAncestorOfDisplayNode(possibleAncestor, node2)) {
break;
}
possibleAncestor = possibleAncestor.supernode;
}
ASDisplayNodeCAssertNotNil(possibleAncestor, @"Could not find a common ancestor between node1: %@ and node2: %@", node1, node2);
return possibleAncestor;
}
extern ASDisplayNode *ASDisplayNodeUltimateParentOfNode(ASDisplayNode *node)
{
// node <- supernode on each loop
// previous <- node on each loop where node is not nil
// previous is the final non-nil value of supernode, i.e. the root node
ASDisplayNode *previousNode = node;
while ((node = [node supernode])) {
previousNode = node;
}
return previousNode;
}
#pragma mark - Placeholders
UIColor *ASDisplayNodeDefaultPlaceholderColor()

View File

@ -125,7 +125,6 @@ typedef NS_OPTIONS(NSUInteger, ASDisplayNodeMethodOverrides) {
// Swizzle to extend the builtin functionality with custom logic
- (BOOL)__shouldLoadViewOrLayer;
- (BOOL)__shouldSize;
- (void)__exitedHierarchy;
// Core implementation of -measureWithSizeRange:. Must be called with _propertyLock held.
- (ASLayout *)__measureWithSizeRange:(ASSizeRange)constrainedSize;

View File

@ -266,7 +266,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@ -301,7 +301,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;