@@ -63,6 +63,22 @@ - (id)initWithFrame:(CGRect)frame
6363 return self;
6464}
6565
66+ - (void )willMoveToWindow : (UIWindow *)newWindow
67+ {
68+ BOOL visible = (newWindow != nil );
69+ if (visible && !_node.inHierarchy ) {
70+ [_node __enterHierarchy ];
71+ }
72+ }
73+
74+ - (void )didMoveToWindow
75+ {
76+ BOOL visible = (self.window != nil );
77+ if (!visible && _node.inHierarchy ) {
78+ [_node __exitHierarchy ];
79+ }
80+ }
81+
6682- (void )willMoveToSuperview : (UIView *)newSuperview
6783{
6884 // Keep the node alive while the view is in a view hierarchy. This helps ensure that async-drawing views can always
@@ -76,28 +92,74 @@ - (void)willMoveToSuperview:(UIView *)newSuperview
7692 else if (currentSuperview && !newSuperview) {
7793 self.keepalive_node = nil ;
7894 }
79- }
80-
81- - (void )willMoveToWindow : (UIWindow *)newWindow
82- {
83- BOOL visible = newWindow != nil ;
84- if (visible && !_node.inHierarchy ) {
85- [_node __enterHierarchy ];
86- } else if (!visible && _node.inHierarchy ) {
87- [_node __exitHierarchy ];
95+
96+ if (newSuperview) {
97+ ASDisplayNode *supernode = _node.supernode ;
98+ BOOL supernodeLoaded = supernode.nodeLoaded ;
99+ ASDisplayNodeAssert (!supernode.isLayerBacked , @" Shouldn't be possible for _ASDisplayView's supernode to be layer-backed." );
100+
101+ BOOL needsSupernodeUpdate = NO ;
102+
103+ if (supernode) {
104+ if (supernodeLoaded) {
105+ if (supernode.layerBacked ) {
106+ // See comment in -didMoveToSuperview. This case should be avoided, but is possible with app-level coding errors.
107+ needsSupernodeUpdate = (supernode.layer != newSuperview.layer );
108+ } else {
109+ // If we have a supernode, compensate for users directly messing with views by hitching up to any new supernode.
110+ needsSupernodeUpdate = (supernode.view != newSuperview);
111+ }
112+ } else {
113+ needsSupernodeUpdate = YES ;
114+ }
115+ } else {
116+ // If we have no supernode and we are now in a view hierarchy, check to see if we can hook up to a supernode.
117+ needsSupernodeUpdate = (newSuperview != nil );
118+ }
119+
120+ if (needsSupernodeUpdate) {
121+ // -removeFromSupernode is called by -addSubnode:, if it is needed.
122+ [newSuperview.asyncdisplaykit_node addSubnode: _node];
123+ }
88124 }
125+
89126}
90127
91128- (void )didMoveToSuperview
92129{
93- // FIXME maybe move this logic into ASDisplayNode addSubnode/removeFromSupernode
94- UIView *superview = self.superview ;
95-
96- // If superview's node is different from supernode's view, fix it by setting supernode to the new superview's node. Got that?
97- if (!superview)
98- [_node __setSupernode: nil ];
99- else if (superview != _node.supernode .view )
100- [_node __setSupernode: superview.asyncdisplaykit_node];
130+ ASDisplayNode *supernode = _node.supernode ;
131+ ASDisplayNodeAssert (!supernode.isLayerBacked , @" Shouldn't be possible for superview's node to be layer-backed." );
132+
133+ if (supernode) {
134+ ASDisplayNodeAssertTrue (_node.nodeLoaded );
135+ UIView *superview = self.superview ;
136+ BOOL supernodeLoaded = supernode.nodeLoaded ;
137+ BOOL needsSupernodeRemoval = NO ;
138+
139+ if (superview) {
140+ // If our new superview is not the same as the supernode's view, or the supernode has no view, disconnect.
141+ if (supernodeLoaded) {
142+ if (supernode.layerBacked ) {
143+ // As asserted at the top, this shouldn't be possible, but in production with assertions disabled it can happen.
144+ // We try to make such code behave as well as feasible because it's not that hard of an error to make if some deep
145+ // child node of a layer-backed node happens to be view-backed, but it is not supported and should be avoided.
146+ needsSupernodeRemoval = (supernode.layer != superview.layer );
147+ } else {
148+ needsSupernodeRemoval = (supernode.view != superview);
149+ }
150+ } else {
151+ needsSupernodeRemoval = YES ;
152+ }
153+ } else {
154+ // If supernode is loaded but our superview is nil, the user manually removed us, so disconnect supernode.
155+ needsSupernodeRemoval = supernodeLoaded;
156+ }
157+
158+ if (needsSupernodeRemoval) {
159+ // The node will only disconnect from its supernode, not removeFromSuperview, in this condition.
160+ [_node removeFromSupernode ];
161+ }
162+ }
101163}
102164
103165- (void )setNeedsDisplay
0 commit comments