When do I need to call setNeedsDisplay in iOS?
You should only be calling setNeedsDisplay if you override drawRect in a subclass of UIView which is basically a custom view drawing something on the screen, like lines, images, or shapes like a rectangle.
So you should call setNeedsDisplay when you make changes to few variables on which this drawing depends and for view to represent that change , you need to call this method which internally will give a call to drawRect and redraw the components.
When you add an imageView or a UIButton as a subview or make changes to any subview, you need not call this method.
You have a view that shows a moving circle, either you touch and move it, or may be timer based animation.
Now for this, you will need a custom view that draws a circle at given center and with given radius.
These are kept as instance variables which are modified to move the circle by changing its center or make it bigger by increasing radius of it.
Now in this case either you will modify these variables(centre or radius) in a loop and timer Or may be by your fingers in touchesEnded and touchesMoved methods.
To reflect the change in this property you need to redraw this view for which you will call setNeedsDisplay.
If I call setneedsdisplay frequently, how often will the drawrect be called? why is that?
From the documentation:
When the actual content of your view changes, it is your responsibility to notify the system that your view needs to be redrawn. You do this by calling your view’s setNeedsDisplay or setNeedsDisplayInRect: method of the view. These methods let the system know that it should update the view during the next drawing cycle. Because it waits until the next drawing cycle to update the view, you can call these methods on multiple views to update them at the same time.
drawRect: will only be called in time for the next frame to be drawn, which means your entire loop will result in
drawRect: only being called once at the next rendering iteration. This saves unnecessary computation as it avoids drawing frames that will never be displayed on the screen. It also lets you make multiple changes in separate places in your code, each time notifying the view that a refresh is needed, without losing performance, since calling
setNeedsDisplay only tells the drawing system that a redraw is needed in the next frame; it doesn't force the immediate rendering of a frame that might never be displayed on the screen.
calling setNeedsDisplay in a for loop
drawRecton the view only gets called at the end
More specifically, it gets called only when your method ends, and the main event loop takes over.
That is precisely the way it is supposed to work:
setNeedsDisplay works like a "tap on the shoulder", which tells the event loop to redraw the view when it gets a chance. No matter how many times you call it, the redraw is not going to happen until your code has finished its work.
Long story short, you should make a call to
setNeedsDisplay only once after the loop has finished.
Do you have to explicitly call setNeedsDisplay after calling setFrame on a UIView?
Short answer: No
setNeedsDisplay when you need method
drawRect to be called, and according to
UIView Class Reference.-
Changing the frame rectangle automatically redisplays the receiver
without invoking the drawRect: method. If you want the drawRect:
method invoked when the frame rectangle changes, set the contentMode
property to UIViewContentModeRedraw.
setNeedsLayout and setNeedsDisplay
Actually the documentation is pretty clear about this:
setNeedsLayout will layout subviews
Call this method on your application’s main thread when you want to adjust the layout of a view’s subviews.
setNeedsDisplay will call for a redraw of your view (
You can use this method or the setNeedsDisplayInRect: to notify the system that your view’s contents need to be redrawn.
Calling setNeedsDisplay in layoutSubviews?
Dont do that, it's not necessary. Set the
contentMode of the view to
Redisplays the view when the bounds change by invoking the setNeedsDisplay method.
Available in iOS 2.0 and later.
Declared in UIView.h.
This will achieve the same effect.