I have a custom class which I derived from the UIView class. What I want to accomplish is just drawing vertical black lines with a predefined distance between. When I override the drawRect method and write my code to draw vertical lines, the view just shows a complete black background. Then I noticed that even an empty overridden drawRect which only calls the superclass' drawRect results in a black background. When I comment out the drawRect, then the view shows through and becomes transparent as I expected.
This is the only code I am using in the drawRect which just calls the superclass method:
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
}
What can be reason of this behavior?
It's quite likely that there is some under-the-hood shenanigans going on with UIView, and that the base class doesn't actually implement drawRect, or some sneaky optimisation is happening.
The documentation does say not to call super if you are directly overriding UIView, and it also says you don't need to implement drawRect if all you do is set a background colour or you populate the content in other ways:
The default implementation of this method does nothing. Subclasses that use native drawing technologies (such as Core Graphics and UIKit) to draw their view’s content should override this method and implement their drawing code there. You do not need to override this method if your view sets its content in other ways. For example, you do not need to override this method if your view just displays a background color or if your view sets its content directly using the underlying layer object. Similarly, you should not override this method if your view uses OpenGL ES to do its drawing.
And:
If you subclass UIView directly, your implementation of this method does not need to call super. However, if you are subclassing a different view class, you should call super at some point in your implementation.
It's therefore quite likely that by calling super you are losing something. You don't show any of your actual drawing code so its difficult to see where you might be going wrong with that, but as a starting point, don't call super if you've directly overridden UIView.
Related
I have a drawInRect method which I wish to use on another UIView, a subview of this view.
Is there a way to do this?
If you are interested in duplicating the drawing, you could put your drawing in a separate function (drawFunct) of the top level view, and just call [self.superview drawFunct] from within the subviews drawInRect.
Calling the drawInRect is generally discouraged.
In my app I have a scrollView with about 20 subviews in it. Each of these subviews has a drawRect method that at the moment looks like this:
- (void)drawRect:(CGRect)rect
{
NSLog(#"drawRect called");
}
When the subviews are added, drawRect is called, however when I scroll it is very slow even though drawRect is not called again.
If I remove the implementation for drawRect, then scrolling is completely normal. Even if I can't get rid of the slow scrolling, is there an alternative to drawRect which I could use instead?
Why are you calling drawRect if it is only logging that it was called? If that is it's only purpose for you, then just don't call it. In fact, I believe when you first create a class that inherits from UIView that has the drawRect method in it, it is commented out and above the commented out drawRect method, it says something along the lines of "Do not call this method if it does not do any drawing on screen as it takes up a significant amount of memory". Basically, don't call it in your case.
Hope this helps.
You could try assigning pre-drawn CGImages to the contents of each custom view's CALayer, before the view first appears. This may be faster than using a drawRect to customize a view's appearance.
I have a UIView subclass. This subclass has multiple subviews. Is it possible to draw a line using core graphics inside a subview that is part of the uiview subclass?
For example, I have a SampleView class, which is a subclass of UIView. Inside this class's header file is the property for UIView *sampleSubView, which is a subview of SampleView. Is it possible to draw a line inside of sampleSubView from the SampleView class implementation?
Thanks for your help!
Josh
If you are asking how a UIView subclass can draw a line on itself, then see the Quartz demo sample code. Basically, you'll override the view's drawRect: method, get the current graphics context, then draw whatever you like onto it.
If you are asking how one view can draw a line on another view, perhaps you need to rethink your architecture.
In Iphone development, I want to draw context in layer.
Then the question is:
What exactly is the context passed into drawLayer:inContext:? Is it the layer's contents's context or the UIview's context?
If this is the UIView's context, which UIView it is?
Thanks in advance.
The context being passed in belongs to the CALayer also returned by that delegate method. Usually, this is a display context, but it can also be an image or PDF context if the layer is manually drawn using -renderInContext:.
CALayers can exist on their own, or be used as the backing for a UIView. All UIViews have a layer behind them, which handles the actual display of that view's content. Drawing in a view actually draws on its layer, and, likewise, drawing in a CALayer that backs a UIView will appear to draw to the view.
As I said, you can create CALayers that exist as separate entities, and add them to existing layers as sublayers for display. At some point, there will need to be a UIView that hosts all of these sublayers within its backing layer in order for these layers to be seen on the iPhone's screen.
Note that according to the UIView class reference:
Since the view is the layer’s
delegate, you should never set the
view as a delegate of another CALayer
object. Additionally, you should never
change the delegate of this layer.
This means that for a UIView's layer, you would be handling the delegate method within the UIView in almost all cases, so the layer passed in to that method would be the view's layer. Sublayers can have anything as their delegate, because they are not attached to a particular view.
There is some information here: Providing Layer Content
If you must draw the layer’s content rather than loading it from an image, you implement the drawLayer:inContext: delegate method. The delegate is passed the layer for which content is required and a CGContextRef to draw the content in.
So normally is the context of your delegate object. In the case of UIVIew, the view itself is the delegate.
I'm not really sure, what am I asking...
...but if make layer composites in separate methods, and draw them to the view also outside of the drawRect: method... ...then could my app performance get raised?
I'm actually subclassed a puzzlePiece:UIView class, where the puzzlepiece gets rendered, but the redraw invoked now with setNeedsDisplay since the drawing implementation takes place in the drawRect: method. The app lags.
Can I improve performance if I get rid of the so called drawRect: method?
The thing wants to get implemented: http://gotoandplay.freeblog.hu/
I think what you want to do here is to have a very single, simple UIView that covers the entire play area. Then put each tile in a CALayer, and attach all the CALayers to the UIView and move them around and rotate them. Then there should not need to be a -drawRect: at all. You'll do all your drawing in your layers, and you should get the best performance that way. CALayer is similar to UIView in principle, but much lighter weight (faster and simpler). CALayer is basically a view that can only draw; it can't handle touches or events. It's parent view has to do that for it. But that let's CALayer be much faster.