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 separa
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.
An Apple engineer provided an alternate recommended solution. Use 2 UIViews, one small and one large, with the larger one with an alpha of 0. Render both, the set the frame of the big one small, and have the animation cross fade as well as zoom both sizes from small to big.
After calling setNeedsDisplay
it may take a moment for the drawRect to get called. Start your animation with a short (0.1f) delay. You could also call the animation method from [self performSelector:withObject:afterDelay:] to add the delay if that's easier.
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).