diff --git a/Source/ASDisplayNode.mm b/Source/ASDisplayNode.mm index 347d41c42..0fc41d40a 100644 --- a/Source/ASDisplayNode.mm +++ b/Source/ASDisplayNode.mm @@ -47,6 +47,7 @@ #import #import #import +#import #import #import #import @@ -876,6 +877,18 @@ - (void)setAutomaticallyRelayoutOnLayoutMarginsChanges:(BOOL)flag _automaticallyRelayoutOnLayoutMarginsChanges = flag; } +- (void)__setNodeController:(ASNodeController *)controller +{ + // See docs for why we don't lock. + if (controller.shouldInvertStrongReference) { + _strongNodeController = controller; + _weakNodeController = nil; + } else { + _weakNodeController = controller; + _strongNodeController = nil; + } +} + #pragma mark - UIResponder #define HANDLE_NODE_RESPONDER_METHOD(__sel) \ diff --git a/Source/ASNodeController+Beta.mm b/Source/ASNodeController+Beta.mm index be6da32fe..6dcd1a079 100644 --- a/Source/ASNodeController+Beta.mm +++ b/Source/ASNodeController+Beta.mm @@ -46,17 +46,14 @@ - (void)setupReferencesWithNode:(ASDisplayNode *)node if (_shouldInvertStrongReference) { // The node should own the controller; weak reference from controller to node. _weakNode = node; - node->_strongNodeController = self; - node->_weakNodeController = nil; _strongNode = nil; } else { // The controller should own the node; weak reference from node to controller. _strongNode = node; - node->_weakNodeController = self; - node->_strongNodeController = nil; _weakNode = nil; } + [node __setNodeController:self]; [node addInterfaceStateDelegate:self]; } diff --git a/Source/Private/ASDisplayNodeInternal.h b/Source/Private/ASDisplayNodeInternal.h index 5e0e1d36e..927513754 100644 --- a/Source/Private/ASDisplayNodeInternal.h +++ b/Source/Private/ASDisplayNodeInternal.h @@ -93,8 +93,6 @@ AS_EXTERN NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimest ASInterfaceState _pendingInterfaceState; UIView *_view; CALayer *_layer; - ASNodeController *_strongNodeController; - __weak ASNodeController *_weakNodeController; std::atomic _atomicFlags; @@ -138,6 +136,9 @@ AS_EXTERN NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimest ASDisplayNode * __weak _supernode; NSMutableArray *_subnodes; + ASNodeController *_strongNodeController; + __weak ASNodeController *_weakNodeController; + // Set this to nil whenever you modify _subnodes NSArray *_cachedSubnodes; @@ -276,6 +277,16 @@ AS_EXTERN NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimest */ - (void)__setNeedsDisplay; +/** + * Setup the node -> controller reference. Strong or weak is based on + * the "shouldInvertStrongReference" property of the controller. + * + * Note: To prevent lock-ordering deadlocks, this method does not take the node's lock. + * In practice, changing the node controller of a node multiple times is not + * supported behavior. + */ +- (void)__setNodeController:(ASNodeController *)controller; + /** * Called whenever the node needs to layout its subnodes and, if it's already loaded, its subviews. Executes the layout pass for the node *