You can try implementing this through Quartz Core using layers (see the CALayer class documentation). Basically, you can have layers hierarchies. You associate each UIView to a different layer, then the layers are rendered together providing a single, composite layer. Besides, you can also apply transforms and animations to layers.
You need to import the QuartzCore header and do something like
#import <QuartzCore/QuartzCore.h>
UIView *mainView = [[UIView alloc] initWithFrame...
UIImageView *imageView = ...
CaLayer *mainViewLayer = mainView.layer;
[mainViewLayer addSubLayer: imageView.layer];
Then, when mainView appears on the screen, all the sublayers are merged together and rendered on screen. What happens is that each view renders its layer, while mainViewLayer is rendered merging together the two layers.
Let me know if this works for you.
You can have as many layers as you like. You can create an arbitrary hierarchi by using the CALayer methods
– addSublayer:
– removeFromSuperlayer
– insertSublayer:atIndex:
– insertSublayer:below:
– insertSublayer:above:
– replaceSublayer:with:
The bounds of an UIView is the rectangle, expressed as a location (x,y) and size (width,height) relative to its own coordinate system (0,0).
The frame of an UIView is the rectangle, expressed as a location (x,y) and size (width,height) relative to the superview it is contained within.
So, imagine a view that has a size of 100x100 (width x height) positioned at 25,25 (x,y) of its superview. The following code prints out this view's bounds and frame:
// This method is in the view controller of the superview
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"bounds.origin.x: %f", label.bounds.origin.x);
NSLog(@"bounds.origin.y: %f", label.bounds.origin.y);
NSLog(@"bounds.size.width: %f", label.bounds.size.width);
NSLog(@"bounds.size.height: %f", label.bounds.size.height);
NSLog(@"frame.origin.x: %f", label.frame.origin.x);
NSLog(@"frame.origin.y: %f", label.frame.origin.y);
NSLog(@"frame.size.width: %f", label.frame.size.width);
NSLog(@"frame.size.height: %f", label.frame.size.height);
}
And the output of this code is:
bounds.origin.x: 0
bounds.origin.y: 0
bounds.size.width: 100
bounds.size.height: 100
frame.origin.x: 25
frame.origin.y: 25
frame.size.width: 100
frame.size.height: 100
So, we can see that in both cases, the width and the height of the view is the same regardless of whether we are looking at the bounds or frame. What is different is the x,y positioning of the view. In the case of the bounds, the x and y coordinates are at 0,0 as these coordinates are relative to the view itself. However, the frame x and y coordinates are relative to the position of the view within the parent view (which earlier we said was at 25,25).
There is also a great presentation that covers UIViews. See slides 1-20 which not only explain the difference between frames and bounds but also show visual examples.
Best Answer
Conceptually all your propositions are similar. All of them would lead to the following steps (some of them done invisibly by UIKit):
The expensive part of the above steps are the first three points. They lead to repeated memory allocation, memory copying, and CPU/GPU communication. On the other hand, what you really want to do is lightweight: Draw a line, probably animating start/end points, width, color, alpha, ...
There's an easy way to do this, completely avoiding the described overhead: Use a CALayer for your line, but instead of redrawing the contents on the CPU just fill it completely with the line's color (setting its
backgroundColor
property to the line's color. Then modify the layer's properties for position, bounds, transform, to make the CALayer cover the exact area of your line.Of course, this approach can only draw straight lines. But it can also be modified to draw complex visual effects by setting the
contents
property to an image. You could, for example have fuzzy edges of a glow effect on the line, using this technique.Though this technique has its limitations, I used it quite often in different apps on the iPhone as well as on the Mac. It always had dramatically superior performance than the core graphics based drawing.
Edit: Code to calculate layer properties:
2nd Edit: Here's a simple test project which shows the dramatical difference in performance between Core Graphics and Core Animation based rendering.
3rd Edit: The results are quite impressive: Rendering 30 draggable views, each connected to each other (resulting in 435 lines) renders smoothly at 60Hz on an iPad 2 using Core Animation. When using the classic approach, the framerate drops to 5 Hz and memory warnings eventually appear.