Foreword, this isn't me losing a view off screen because I did the transform wrong, it's weirder.
Problem is, if I use an .m34 transform to achieve the perspective I need, the view hierarchy breaks, but remove the transform and it draws everything correctly.
Aquí hay un ejemplo.
I have a background image (subviewOne), a menu(subviewTwo), and an object on top of all of that which I apply the CATransform3D to (subviewThree).
CALayer *layer = subviewThree.layer; CATransform3D perspectiveTransform = CATransform3DIdentity; perspectiveTransform.m34 = -1.0 / 500; layer.transform = perspectiveTransform;
Prior to applying this code, the view hierarchy was, and still is on iOS 5:
(bottom to top) subviewOne->subviewTwo->subviewThree
After applying it, I end up with:
(bottom to top still) subviewTwo->subviewOne->subviewThree
Now, subviewThree still has the perspective transform applied to it, and is in the correct spot, on top of everything else, same as on iOS5. However, the Menu/subviewTwo, is now hidden by the background image/subviewOne, and nothing I do will get it to be drawn on top of the subviewOne. No amount of insertSubviewAtIndex:, bringSubviewToFront, sendSubviewToBack, etc, will make the view draw correctly.
This is incredibly peculiar particularly because the views that are drawn out of order are NO having any kind of CATransform3D applied to them.
I have verified this independently in two different apps and multiple devices 6 devices. iOS5 draws everything correctly, and if I remove those four lines, everything draws correctly, but nothing I've tried on iOS 6 stops the .m34 from breaking the view ordering. It's not always as simplistic as the example I've provided, but this is the most demonstrable case I have witnessed.
Has anyone else experienced this, solved this?
Edit: More info for comment.
Yeah, typo with the extra *.
Figure there's an Imageview, QuadCurve Menu, and Textview.
I was calling the method with the .m34 in the viewDidLoad, but swapped it to the viewDidAppear real quick to check for you.
Doesn't matter. Don't get me wrong, the subviews are listed in the correct order when you call
NSLog(@"%@", [self.view.subviews description]);
They just aren't drawn on screen correctly.
In desperation, I wrote some crazy weird code, and I discovered the following.
I can call the method that draws the menu on a 10 second delay,
[self performSelector:@selector(createQuadCurveMenu) withObject:nil afterDelay:10];
que termina en
As well as a totally superfluous
and it's still drawn behind an imageView that is set as the lowest subview in the .xib.
I have verified this two ways. I can go into the .xib and set the imageView to hidden, and running again I can see the menu, now that the imageView isn't covering it. I can also just comment out the code that applies the .m34 transform to the textView, and the menu then again correctly appears on top of the imageView. Again, none of this happens on iOS5 and iOS4.
At this point, I'm starting to think that it's a bug inside iOS6 itself, and have been waiting for the NDA to expire so I can ask here if anyone else has experienced it.
preguntado el 22 de septiembre de 12 a las 18:09
Pretty sure this is an iOS 6 bug: I've blogged about it here: Error de renderizado de iOS 6: la rotación 3D hace que las capas se rendericen sin respetar la jerarquía de vistas.
Good news: You can work around the bug by setting zPositions on the affected layers: set the zPositions in increasing order of the view hierarchy. So if I've understood correctly, you want:
subviewOne.layer.zPosition = 0; subviewTwo.layer.zPosition = 1000; subviewThree.layer.zPosition = 2000;
Check out the blog for more info, including a link to the Open Radar version of the bug I've logged with Apple.
Also, this might be considered a duplicate of this post: Pesadilla de la jerarquía de vistas de iOS 6. It has the same bug source and solution, although the symptoms you both describe are different.