In my app I have a number of small subviews. When the user taps a subview, I place one separate view over top of the tapped subview (same size) and then animate this separate view to full-screen size.
The enlarging view is custom-drawn, which is creating a big problem with this approach. If I create the enlarging view in my main view's viewDidLoad
method and set its frame to full-screen size, the view's drawRect
method is called immediately, and the view is properly rendered full-size. If I then use this view in the animation, everything works as expected.
However, I need this enlarging view to be different depending on which subview was tapped, so I need to re-create/re-draw it each time. The problem is that when I do this in response to a touch event, the view's drawRect
method does not get called until the animation begins, at which time the view's frame is small instead of full-screen, and as a result everything is drawn wrong.
In my code for the touch event, I'm explicitly setting the view's frame to fullscreen and calling setNeedsDisplay
before starting the animation, but this has no effect - drawRect
just isn't called until the animation begins.
Is there any way to force a redraw, so that the view is drawn while its frame is the size I want it to be?
As I commented above, Joe asked something similar (as a more general question) here, to which Tom Swift provided an answer that manipulates the current run loop.
His suggestion was to force the run loop through one iteration immediately after you call -setNeedsDisplay
using the following code:
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate date]];
There are some caveats to this approach, which are discussed in the comments there.
Also, it was pointed out there that
[CATransaction flush];
may also achieve the same effect of forcing an immediate redraw of the view.
The proper way to do this is to simply divide up your method.
Just call setNeedsDisplay
, then return without animating. Wait until the drawRect
that sets everything up correctly has finished its redraw, and then have it queue up another method that starts your desired animation (via queuing an operation or a notification). Then start the animation. This can all happen fairly quickly (at frame rate), and involves no extra (dangerous) recursive run loop calls or CATransaction
calls (which may cause extra GPU setups).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With