Rotating the UIPageViewController in the container view controller

I have a UIViewController that contains other ViewControllers. The initial ViewController is set to viewDidLoad:

FirstViewController *first = [FirstViewController alloc] init]; first.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; first.view.frame = m_content.frame; [self addChildViewController:first]; [m_content.view addSubview:first.view]; [first didMoveToParentViewController:self]; m_activeViewController = first; 

This container controller automatically implemented ForwardAppearanceAndRotationMethodsToChildViewControllers to return YES. He also implemented to manually change the direction of rotation for inactive ViewControllers.

 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return YES; } - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { for(UIViewController *vc in m_viewControllers) { if(vc != [m_activeViewController] [vc willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; } } - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { for(UIViewController *vc in m_viewControllers) { if(vc != [m_activeViewController] [vc didRotateFromInterfaceOrientation:fromInterfaceOrientation]; } } 

When the menu button is pressed, I make a transition between ViewControllers.

 - (void)onMenuItemTapped:(id)sender { UIViewController *vc = [m_viewControllers objectAtIndex:sender.tag]; vc.view.frame = m_content.frame; [self addChildViewController:vc]; [self transitionFromViewController:m_activeViewController toViewController:vc duration:0 options:UIViewAnimationOptionTransitionNone animations:nil completion:^(BOOL finished) { [vc didMoveToParentViewController:self]; [m_activeViewController removeFromParentViewController]; m_activeViewController = vc; }]; } 

This transition works fine for my β€œnormal” ViewControllers, and they display correctly after changing orientation, even if they are inactive. However, one of these Child View controllers, called SecondCV, has a UIPageViewController as a child view controller. I have UIPageViewControllerDelegate and UIPageViewControllerDataSource installed for this SecondCV and pageViewController: spineLocationForInterfaceOrientation:. I return UIPageViewControllerSpineLocationMin for Portrait and UIPageViewControllerSpineLocationMid for landscape. The rotation for this SecondVC works correctly when it is active - there are two pages on the landscape, and one is displayed correctly in portrait mode. But when this SecondVC is not active, the rotation is incorrect. Even if pageViewController: spineLocationForInterfaceOrientation: is called , there is another page in both Portrait and Landscape modes. I have been trying to fix this for some time, but I do not see other options. Do you have any idea how to fix this?

Thanks.

+6
source share
2 answers

I solved this difficulty.

In fact, SecondVC has been rotated correctly, or at least the location of the spine has been changed correctly. Therefore, when I turned the device, and SecondVC was not the active view controller in the parent view, it received HAS rotation messages and pageViewController: spineLocationForInterfaceOrientation:. I set the right spine location for the new interface orientation and called setViewControllers on the SecondVC page view controller. The problem was that even if I installed two view controllers for UIPageViewControllerSpineLocationMid , after displaying SecondVC there was only one left, for example, in UIPageViewControllerSpineLocationMin.

I have a β€œfixed” problem by installing the view controllers again in the page view controller in viewWillAppear: because when this method is called, the spine location for the page view controller is correct and based on this, the information I set is two pages (controllers view)

 - (void)viewWillAppear:(BOOL)animated { if(m_pageController.spineLocation == UIPageViewControllerSpineLocationMid) { LeftPageController *left; RightPageController *right; if(m_pageController.viewControllers.count > 0) { left = [m_pageController.viewControllers objectAtIndex:0]; right = [m_storyboard instantiateViewControllerWithIdentifier:@"rightPage"]; [right loadView]; } [m_pageController setViewControllers:[NSArray arrayWithObjects:left, right, nil] direction:UIPageViewControllerNavigationDirectionForward | UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil]; [m_left hideGallery]; } if(m_pageController.spineLocation == UIPageViewControllerSpineLocationMin) { [m_pageController setViewControllers:[NSArray arrayWithObject:[m_pageController.viewControllers objectAtIndex:0]] direction:UIPageViewControllerNavigationDirectionForward | UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil]; } [super viewWillAppear:animated]; } - (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation { if(UIInterfaceOrientationIsPortrait(orientation)) { LeftPageController *left = [pageViewController.viewControllers objectAtIndex:0]; [pageViewController setViewControllers:[NSArray arrayWithObject:left] direction:UIPageViewControllerNavigationDirectionForward | UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil]; pageViewController.doubleSided = NO; return UIPageViewControllerSpineLocationMin; } if(UIInterfaceOrientationIsLandscape(orientation)) { LeftPageController *left; RightPageController *right; if(pageViewController.viewControllers.count > 0) { left = [pageViewController.viewControllers objectAtIndex:0]; right = [m_storyboard instantiateViewControllerWithIdentifier:@"rightPage"]; [right loadView]; } [pageViewController setViewControllers:[NSArray arrayWithObjects:left,right, nil] direction:UIPageViewControllerNavigationDirectionForward | UIPageViewControllerNavigationDirectionReverse animated:NO completion:nil]; return UIPageViewControllerSpineLocationMid; } return UIPageViewControllerSpineLocationMin; } 

I know that I am doing the same thing twice, but this is the price that I am willing to pay in this case. Why, after calling pageViewController: spineLocationForInterfaceOrientation: and setting two view controllers for Landscape, when SecondVC is inactive, only one ViewController in m_pageController in viewWillAppear: after activation, SecondVC remains a mystery to me.

+1
source

I have included the following code to solve this problem in iOS 6:

 - (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation { NSArray *allPageControllers = pageViewController.viewControllers if (allPageControllers != nil) { [self setViewControllers:allPageControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil]; } else { UIViewController *defaultViewController = [[UIViewController alloc] init]; [self setViewControllers:[NSArray arrayWithObject:defaultViewController] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil]; [defaultViewController release]; } return UIPageViewControllerSpineLocationMin; } 

Hope this helps someone!

0
source

Source: https://habr.com/ru/post/913114/


All Articles