Making the MKMapView transparent but keeping overlays opaque - iphone

Is there a way to make the map somewhat transparent but keep all the added overlays opaque?
Adjusting the alpha for the map will of course set it for the overlays as well.

You would have to fiddle around with MKMapView's subviews which is possible but completely undocumented and not recommended by Apple. Basically you'd need to find the subview with the actual map and set its alpha. No guarantee it'll actually work!

Related

Does CALayer shouldRasterize propagate to all sublayers?

If I set shouldRasterize = YES on a CALayer, do I have to set it on each of the sublayers as well if I wanted the whole hierarchy to be flattened for better animation performance?
I'm asking because when I set shouldRasterize = YES on my root layer and enable "Color Blended Layers" in Instruments, all the sublayers are still there and marked as blended. It's not flattening anything.
Setting shouldRasterize does not do quite what you are thinking it does. In order to composite the look of the parent view, rasterized or not, it has to check subviews to see if they are opaque or transparent. When child objects are opaque, they do not need to be blended. When they are transparent, the view needs to be blended with whatever is behind them (or higher in the hierarchy).
So, shouldRasterize will not affect the green/red you see using Instruments. In order to have everything green, you'll need to not use transparency and have all your child objects be opaque. Sometimes its unavoidable to still have red areas depending on your design. The instrument is just there to help you optimize ones that could be opaque and reduce the amount of blending the GPU has to do.
Edit:
To explain further, suppose you have a UILabel and its sitting on top of a photo. You only want to see the text and not its background color, so you set its backgroundColor to clear, and the opaque property to NO. In instruments, this will now appear red. The GPU has to blend this transparency over the image behind it, performing two draw operations instead of one.
If we had set opaque to YES and gave it a solid background color, the view would now show up green in instruments because it didn't have to blend that view with any other view.
So, whether the layer is rasterized or not, it still has to composite its child views so shouldRasterize really has no effect either way on what you see in Instruments.

CATiledLayer and UIScrollView, caching old data for some zoom levels

I have a CATiledLayer set up to dynamically re-draw some graphics I'm creating with Quartz.
This view is added as the content view of a scroll view, and as I scroll and zoom the graphic is redrawing at the proper resolution and doing exactly as I expected.
My problem is that If I change the values that generate the graphic (it is a visualization of a graph like structure), then setNeedsDisplay on the view, the changes will apply and be shown at some zoom levels, but if you zoom out it will show the old graphic that was generated. Zooming in again goes back to the proper graphic.
I assume that the different zoom levels in the tiled layer are being cached, and so the update isn't being applied to the already cached zoom levels.
My question is, if this is the case, is there any way to force the CATiledLayer to redraw not from the cached data? And if not, does anyone know what could be causing the problem?
Not sure if you are still having this issue but I have run into it myself recently. This seems like the same issue from Clear CATiledLayers Cache When Changing Images The answer seems to be to set the layer.content to nil and then call for a refresh with setNeedsDisplay or setNeedsDisplayInRect:. So wherever you would have called setNeedsDisplay to refresh the view after wanting it cleared you would instead use:
layer.content = nil;
[layer setNeedsDisplay];
This seems to work for me though in the comments for the answer of the above linked question there are warnings against directly setting the layer.content property. Aside from possibly removing and re-adding the layer though I have not been able to come up with any other options.

ContentScaleFactor on UIKit elements broken?

I'm trying to make sure my UILabel's and UITextView's stay sharp when they exist within a UIScrollView. I came along the 'contentScaleFactor' property on the UIView class, it seems to work perfectly fine on custom drawing but UITextView's and Labels just refuse to redraw themselves at the right contentscale.
http://pastebin.com/PBjhjMbR
Maybe this is due that the actual views that draw the text are a subview of these classes?
You need to set contentScaleFactor recursively on all subviews and also call setNeedsDisplay on each view that you set it on to make them display at higher quality. I have also found that it is not worth setting it on a UIImageView because they won't render at higher quality anyway so there's no point in wasting memory by making their backing layers bigger.

Why opaque views are more effective on iPhone?

I tried to find other reasons why opaque views are better than transparent. However, the only sensible reason I came up with is that the view behind the opaque one doesn't need to draw its content at that place.
Is this a wrong assumption and are there other good reasons?
Thanks.
This is the right assumption. Directly from Apple documentation:
opaque
A Boolean value that determines
whether the receiver is opaque.
#property(nonatomic, getter=isOpaque) BOOL opaque
Discussion
This property provides a hint to the drawing system
as to how it should treat the view. If
set to YES, the drawing system treats
the view as fully opaque, which allows
the drawing system to optimize some
drawing operations and improve
performance. If set to NO, the drawing
system composites the view normally
with other content. The default value
of this property is YES.
An opaque view is expected to fill its
bounds with entirely opaque
content—that is, the content should
have an alpha value of 1.0. If the
view is opaque and either does not
fill its bounds or contains wholly or
partially transparent content, the
results are unpredictable. You should
always set the value of this property
to NO if the view is fully or
partially transparent.
Aside from being able to avoid drawing the background view, there are a few other reasons it's faster, related to compositing:
1) There's no need to blend the foreground and background views, which saves some math done on every pixel
2) If the view moves, its pixels can simply be blitted to their new locations without any redrawing at all. This is a huge deal for scrolling performance, even on desktop computers, let alone mobile devices.

UIView clipsToBounds property: Does it improve performance?

The documentation says that the clipsToBounds property of UIView will clip the drawing to the bounds, or more precisely that the subView can't draw outside of the bounds of the superView.
Sounds nice, but what does that mean in practice?
If I set that to YES, then my subView will automatically only draw those parts which are not outside the bounds of the superView. so it increases the overall performance or do I still have to make sure that I don't create any views that are not visible, i.e. inside a UIScrollView ?
I think it's the opposite: turning on clipping hurts performance because it has to set up a clipping mask. I vaguely remember reading this somewhere, but I can't find it now.
The use case for clipsToBounds is more for subviews which are partially outside the main view. For example, I have a (circular) subview on the edge of its parent (rectangular) UIView. If you set clipsToBounds to YES, only half the circle/subview will be shown. If set to NO, the whole circle will show up. Just encountered this so wanted to share.
The (possible) performance hit is only deterministic if you know the view hierarchy. As mentioned above, usually the renderer will use GPU cycles to draw the view UNLESS some view within the hierarchy uses drawRect:. This does not affect OpenGL ES application because drawRect:is omitted in this type of apps.
From my understanding, determining and displaying the clipped area may take less cycles than actually calculating/drawing/blending the whole view. As of OpenGL ES 2.0 clipping can be calculated in GPU.