问题
I am presenting UIActivityViewController from my controller. I've encountered issues with rotations. After some data sharing option is chosen, let's say "Mail", mail compose view controller is presented. But if I rotate the device and dismiss the mail controller afterwards, my VC is not rotated to the current orientation. I've tried to set up the completion handler for UIActivityViewController as following:
1)
[activityViewController setCompletionHandler:^(NSString *activityType, BOOL completed){
[UIViewController attemptRotationToDeviceOrientation];
}];
or
2)
[activityViewController setCompletionHandler:^(NSString *activityType, BOOL completed){
UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation];
[self layoutForInterfaceOrientation:currentOrientation];
}];
The first solution did not help at all. The second solution left the navigation bar unrotated (12 points difference in height).
Please advise how to handle this situation.
回答1:
I've resolved the issue. First of all, I should say that my VC is always rotated to portrait after MailComposeVC is dismissed regardless of the current device orientation and its state before showing a mail...
And the only VC method that gets called during auto rotation when MailComposeVC is on screen is viewWillLayoutSubviews/viewDidLayoutSubviews
. (willAnimateRotationToInterfaceOrientation
is not called!)
So, I reset the navigation bar to recover its height and call my custom layout method if my VC is invisible, like that:
(void) viewDidLayoutSubviews {
// HACK: forcing the bars to refresh themselves - this helps to get the shorter version when switching to landscape and the taller one when going back!!!
if (amIhidden) {
[self.navigationController setNavigationBarHidden:YES animated:NO];
[self.navigationController setNavigationBarHidden:NO animated:NO];
UIInterfaceOrientation currentOrientation = [[UIApplication sharedApplication] statusBarOrientation];
[self layoutForInterfaceOrientation:currentOrientation];
}
}
amIhidden BOOL
is set when presenting MailComposeViewController, as following:
UIActivityViewController *activityViewController = [[UIActivityViewController alloc]
initWithActivityItems:@[self]
applicationActivities:nil];
amIhidden = YES;
[activityViewController setCompletionHandler:^(NSString *activityType, BOOL completed){
amIhidden = NO;
}];
[self presentViewController:activityViewController animated:YES completion:nil];
Hope, my solution will help to somebody else!
回答2:
If the accepted solution didn't work for you ( like me ) I have answered similar question which is easy and clean. Objective c - UIActivityViewController orientation mode
回答3:
I figured out a solution in Swift 3. But I think it should also work in Objective-C.
In AppDelegate
function application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask
, return the right orientation for specific view controller.
The tricky part is that you have to dig out the view controller which you want the orientation to be based on. Like in my case, when UIActivityViewController
is presented, window?.currentViewController()
and window?.topMostController()
are both UIActivityViewController
. Because I use UIActivityViewController
in other places, I can't use it as the clue. Then I checked window?.currentViewController()?.presentingViewController
and found it is a UINavigationController
. Since I know the view controller I wanna base on is the top view controller of that UINavigationController
, my solution is as following:
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if window?.currentViewController() is MyLandscapeViewController{
return [UIInterfaceOrientationMask.landscapeLeft, UIInterfaceOrientationMask.landscapeRight]
}
if let presenting = window?.currentViewController()?.presentingViewController{
if let nav = presenting as? UINavigationController{
if nav.topViewController is MyLandscapeViewController{
return [UIInterfaceOrientationMask.landscapeLeft, UIInterfaceOrientationMask.landscapeRight]
}
}
}
return UIInterfaceOrientationMask.portrait;
}
With this code, the screen no longer rotate to portrait but stay in landscape after a sharing option is chosen when MyLandscapeViewController is presented.
来源:https://stackoverflow.com/questions/14609911/correct-orientation-after-uiactivityviewcontroller-is-dismissed