Positioned Off-Screen vs Hidden - ios

I'm building an app in Xcode, using interface builder. One VC has some objects I have positioned off-screen (-600 leading to leading margin, for example). On button press, they are animated into the view.
My question is, what is the effect of having views off screen? Does it take up memory? Should I hide these views after they've animated back off to the side?

Any view that has been alloc'ed and init'ed will take up memory, off screen or not. This is more obvious in Obj-c as its when you call [UIView alloc] init] buts its still the same in swift UIView(frame: ).
The view won't draw its layers until it's been added as a subview. The view will still draw itself if it's off the parents visible rect by default. You can set the parents view to clipsToBounds = YES (swift clipsToBounds = true) and it won't draw any of its child views off screen saving some memory as the child views won't draw their layers. Not sure it's worth the effort to do that though as you only have them off screen temporarily and then animate on.
If you can you should instantiate the views right before you animate them on screen, you should 'removeFromSuperview' and set to nil, or remove them from your array, however you are storing them once the animation is done.

Related

drawRect over subviews?

I created a container view that holds a bunch of child views - a collection view, a custom toolbar and some bits and pieces.
The design has a border on the top, left and right sides, but not the bottom, so I overrode drawRect to include border.
When I added the toolbar I noticed that it appears over the top of the border. (For some reason I initially thought it wouldn't but of course it does!).
Is there anyway I can tell drawRect to draw over the top of my subviews?
Of course there's loads of other ways to solve my problem (adjust the toolbar's frame for example) however I'm asking this question in order to get a deep understanding of how drawing works in relation to compositing and the view hierarchy.
Drawing happens beneath all subviews of a UIView. Think of it as being on the very base - an actual part of your view - and then each subview is added on top of your view. To make the drawing above the subviews is the same as wanting for the subviews to appear under the view, while still being subviews. Perhaps that analogy makes it clearer why it must always be on the bottom. And it also leads you logically to the solution:
To get the drawing to appear above subviews, simply create a new UIView subclass to place the drawing code inside, and place this above all other subviews.
It might also be a good idea to override your UIView's addSubview: implementation, to ensure your subview always remains on top.
I believe you can't, since the drawRect is called first for the view and when it has finished drawing drawRect is called for subviews to draw over it. Maybe just make another subview on top of that view that has the borders you need and is transparent everywhere else?
Subviews are drawn on top of their super views. So the answer to your question is no.
At the time when you draw the border on your container view, Cocoa hasn't even started drawing the toolbar yet.
I guess you could make the top of the border a subview or move the toolbar down a bit.

UIView animation clips view bounds. Any way to prevent clipping?

I have a UIView animation that does a vertical flip animation transition from one view to another. The problem is that the view has some overflowed content (achieved by setting clipsToBounds to NO on the view), and during the animation, the overflowed content gets clipped.
Is there any way to prevent CoreAnimation from clipping the views?
Screenshots
Normal view (notice the paperclip and overhanging rope along the top edge of the map):
Animation in flight: (paperclip and rope are clipped)
I'd recommend placing all the views which rotate inside of a transparent view (kind of placeholder for "map" and "clip"), and applying animation to it rather than to your map view.
Try to set placeholder view's size the way its subviews won't overflow, so you can not worry about hacking clipsToBounds.
have you tried: myView.layer.masksToBounds = NO; ?

UIView drop shadow on only one other view

There are a lot of questions about how to draw a drop shadow for a view. But how can I have my view cast a shadow that is received only by one other view?
If view A is the view with the shadow and view B is the parent of A, you can set masksToBounds which is a property of B's layer to YES.
Contents of B and its subviews will not be shown outside of B. They will be clipped.
More detail here: What UIView layer.masksToBounds is doing if set to YES?
However, if you want the shadow drops on more complex scene, you might need to be a little more specific.
Make an app with a white background.
Make your view plus shadow.
Take a screen shot.
Use the screen shot in your original app.
Of course you could also make the picture on the fly in code, but that is a bit more challenging. In any case, it would be code you do not need in your final app.

UIButtons non-responsive after being moved in from off iPad screen

The description might be a bit confusing, I've added pictures to try to illustrate what I'm describing. Please let me know what I can clarify to help.
I have an iPad application with a main view that is a xib. The size of the xib is 1024 by 1384 and is meant to be viewed in landscape mode. There is a row of buttons that are visible at the bottom of the iPad screen. When one of the buttons is pressed I move the frame so that these buttons are now at the top of the visible portion of the screen. There are additional elements that start out offscreen but then come onscreen after the move.
The problem I'm having is that the UIButton that starts offscreen is not calling the IBAction associated with it.
I have tried to setUserEnabled to YES for it but that doesn't seem to be making any difference either. I've also tried setNeedsDisplay after the animation is complete.
Anyone have any ideas?
When you add the view to the screen, it changes the view's size to fit the visible portion on the screen. As such, your frame is smaller than the total content area of the view. Moving the frame won't do anything for you; it will move the existing visible content up, but it won't change the view to show new visible content.
Instead, you want to be changing the view's bounds.origin, which will change the visible portion of the view's content.
Edit:
Note that even though the view was shrunk, I suspect that the clipsToBounds property on your main view was set to NO. That means that it will actually continue displaying content outside of the bounds, which is why it shows up. However, hit-testing only works on the actual frames of the view. All that stuff that shows up outside the bounds is still visible, but it's not interactible.

controlling orientation changes from within a subview

Have a very large program where there is always a superview that just encompasses a custom segment controller. This view sits at the top of screen and controls navigation in several ways.
So the problem arose in only a selected few view controllers where everything was 100% programmaticly created. Essentially CGRect are not being defined in the property dynamic coordinates. But are not being recalculated on orientation change. Does anyone have a simple way to control this in the subview? I'm about to code something in the superview to pass to orientation to other subviews.. but there has to be a better way. Ideas?
Couple of pointers:
You can use auto-resizing masks to determine what happens to your views when their bounds change (ie, when the orientation changes). So UIViewAutoresizingFlexibleWidth means your view will 'stretch' proportionally with the superview when the bounds are changed. UIViewAutoresizingFlexibleLeftMargin means your view will effectively be right-aligned, as the left margin will adjust according to the width, etc etc.
Sometimes auto-resizing masks aren't enough - perhaps you have to change the view's content on an orientation, or do a complex animation. In this case, you use the willAnimateRotationToInterfaceOrientation method in your view controller. Your subviews might have a custom adjustForOrientation method that you've written that you can trigger when willAnimateRotation... is called.
Finally, on iOS 5 you can actually nest view controllers inside of view controllers, in which case orientation events get passed through automatically...but this is probably needlessly complex for what you're trying to do.

Resources