Based on comments and tests, here's what I'm currently doing:
When I get the image from the UIImageController
, I retain it in a class ivar and dismiss the image picker. I show a view that blocks my main view and schedule a NSTimer event to do the compression in a second, then return to the caller.
This lets the animation run that dismisses the image controller. My blocker view is revealed under it.
(The blocker view fills the entire content area of the navigation controller, and is solid black with a UIActivityIndicatorView
.)
- (void)imagePickerController: (UIImagePickerController *)picker
didFinishPickingImage: (UIImage *)selectedImage
editingInfo: (NSDictionary *)editingInfo;
{
busyView.userInteractionEnabled = YES;
busyView.alpha = 0.7f;
mainView.userInteractionEnabled = NO;
[self dismissModalViewControllerAnimated: YES];
[NSTimer scheduledTimerWithTimeInterval: 1.0f
target: self
selector: @selector(compress:)
userInfo: selectedImage
repeats: NO];
}
When the timer fires, I compress the image using JPEG (because it's faster than PNG, despite intuition) and fade away the blocker view.
- (void)compress: (NSTimer *)inTimer;
{
[self gotJPEG: UIImageJPEGRepresentation( inTimer.userInfo, 0.5f )];
[UIView beginAnimations: @"PostCompressFade" context: nil];
[UIView setAnimationDuration: 0.5];
busyView.userInteractionEnabled = NO;
busyView.alpha = 0.0f;
[UIView commitAnimations];
mainView.userInteractionEnabled = YES;
}
Although this adds a second do the processing, it gets the image picker out of the way faster so it no longer feels like my application has frozen. The animation from the UIActivityIndicatorView
does run while UIImageJPEGRepresentation
is working.
A better answer than using the NSTimer
with 1 second delay would be to get an event when the animation from dismissModalViewControllerAnimated:
finishes, but I'm not sure how to do this.
(I don't consider this solved yet.)