Animating the present and dismiss of a Share Extension with custom UI on iOS 8
Here is the cleanest solution I found so far to animate my custom view controller in and out!
Animate IN:
- (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; self.view.transform = CGAffineTransformMakeTranslation(0, self.view.frame.size.height); [UIView animateWithDuration:0.25 animations:^ { self.view.transform = CGAffineTransformIdentity; }];}
Dismiss:
- (void)dismiss{ [UIView animateWithDuration:0.20 animations:^ { self.view.transform = CGAffineTransformMakeTranslation(0, self.view.frame.size.height); } completion:^(BOOL finished) { [self.extensionContext completeRequestReturningItems:nil completionHandler:nil]; }];}
Instead of animating the UIViewController
's view
, I am suggesting a bit different approach.
I have created a dummy UIViewController
(called PresentingViewController
here on) whose view.backgroundColor
is set to [UIColor clearColor]
. I then present the intended custom UIViewController
modally (or custom animation if you like) on top.
This is the code for the PresentingViewController
:
@implementation PresentingViewController- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; [self performSegueWithIdentifier:@"PresentController" sender:self];}- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"PresentController"]) { CustomViewController *controller = (CustomViewController *)[segue.destinationViewController topViewController]; controller.context = self.extensionContext; }}- (IBAction)unwindFromShareVC:(UIStoryboardSegue *)segue { [self dismissViewControllerAnimated:YES completion:^{ NSError *error = [NSError errorWithDomain:@"Cancelled" code:0 userInfo:nil]; [self.extensionContext cancelRequestWithError:error]; }];}@end
Notes:
extensionContext
is set only on thePresentingViewController
and thus it is required to be passed on to theCustomViewController
.- For animating dismiss, I was unable to use an unwind segue, because it was difficult to know the completion of dismissal. So I used dismissViewControllerAnimated:completion: instead.