Mof
Mof

Reputation: 363

UIView insertSubview atIndex to move a subview odd behaviour

I have a UIView which in this case has 4 subviews. I want to be able to change the order the subviews are in, but I can't seem to use

 [UIView insertSubview: atIndex:]

In one specific case if I call it to move an item from index 2 to index 1, it instead places it at index 0. Here is the debugger output:

(lldb) po self.subviews
<__NSArrayM 0x600003084f30>(
<ViewA: 0x7fb075cee4c0; frame = (20 12; 399.5 35.32); ...>,
<ViewB: 0x7fb075cf1b60; frame = (20 59.32; 399.5 27.5); ...>,
<ViewC: 0x7fb075cef2c0; frame = (20 98.82; 399.5 67); ...>,
<ViewD: 0x7fb075cfa750; baseClass = UIButton; frame = (20 177.82; 399.5 35); ...>)

(lldb) po self.subviews[2]
<ViewC: 0x7fb075cef2c0; frame = (20 98.82; 399.5 67); ...>

(lldb) po [self insertSubview:self.subviews[2] atIndex:1]
(lldb) po self.subviews
<__NSArrayM 0x600003085020>(
<ViewC: 0x7fb075cef2c0; frame = (20 98.82; 399.5 67); ...>,
<ViewA: 0x7fb075cee4c0; frame = (20 12; 399.5 35.32); ...>,
<ViewB: 0x7fb075cf1b60; frame = (20 59.32; 399.5 27.5); ...>,
<ViewD: 0x7fb075cfa750; baseClass = UIButton; frame = (20 177.82; 399.5 35); ...>)

As you can see I attempted to move ViewC to after ViewA but instead it went to before it. If I instead use

[UIView insertSubView: aboveSubview:]

It works fine.

I have tried removing the view before I do the insert but that gave me the same result. This is very odd and I feel like I'm missing a fundamental part of UIView's here. I can live with the workaround, but I really would prefer understanding why it's not working.

[UPDATE] There was one extra bit of information which turns out to be essential. I have an extra CALayer which I use to highlight the parent view. So if I disable this CALayer, then it all works fine. I could be wrong, but this implies that insertSubviews actually moves the CALayers around. Does this mean self.subviews is just a helper function to get the UIViews associated with the CALayers based on self.layer.sublayers?. Anyway I found my culprit and it looks like there is definitely a deficiency in my understanding of CALayers to subviews.

Upvotes: 2

Views: 489

Answers (1)

gulyashki
gulyashki

Reputation: 459

This is interesting.

UIView is simply a wrapper around CALayer which provides functionality like gesture handling etc. What we really see onscreen is the layer tree. It seems that the index parameter that we pass to insertSubview:atIndex: is the index of the view's layer in the layer tree which causes confusion. After you insert the subview, the subviews array is arranged according to the position of the backing layer of the views relative to that of other subviews.

In your case I assume your highlight layer is at index 0, that's why when you insert subview at index 1 it goes at 0 position in the subviews array, because it's backing layer is actually below that of all other subviews' and above the CALayer that you use to highlight.

Upvotes: 4

Related Questions