IOS8 how to move an active popover

I developed an application for iOS7 and am now trying to update it for iOS8. The problem I have is the following:

The orientation of the application screen can be rotated, and in some cases several buttons move sharply. I have several popovers that point to these buttons, so if the popup is open when the screen rotates, the button moves, I also need a popover.

In iOS7, I did the following: When the screen is rotated, I updated the restrictions

- (void) updateViewConstraints { if (UIInterfaceOrientationIsLandscape(self.interfaceOrientation)) { self.Button.constant = (CGFloat)10; } else { self.Button.constant = (CGFloat)5; } [super updateViewConstraints]; } 

I also move popover

 - (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{ if(TempDisplayPopoverController == examplePopoverController) { [examplePopoverController presentPopoverFromRect:[self ExamplePopoverPosition] inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; } } 

I initially download popover

 - (void) LoadPopover{ examplePopover = [[examplep alloc] initWithNibName:@"exampleP" bundle:nil]; [examplePopover setDelegate:self]; examplePopoverController = [[UIPopoverController alloc] initWithContentViewController: examplePopover]; [examplePopoverController setDelegate:self]; examplePopoverController.popoverContentSize = examplePopover.view.frame.size; TempDisplayPopoverController = examplePopoverController; if ([examplePopoverController isPopoverVisible]) { [examplePopoverController dismissPopoverAnimated:YES]; } else { [examplePopoverController presentPopoverFromRect:[self ExamplePopoverPosition] inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; } } 

[self ExamplePopoverPosition] just returns the position of the button.

It all worked great, I was happy, the iPad was happy and everything behaved.

Now because of iOS8, I need to change a few bits.

self.interfaceOrientation depreciates

[examplePopoverController presentPopoverFromRect:[self ExamplePopoverPosition] inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];

in didRotateFromInterfaceOrientation throws an error

"Application tried to represent an active popover presentation: <UIPopoverPresentationController: 0x7bf59280>"

I managed to fix self.interfaceOrientation

 - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { [self SetUpScreen:toInterfaceOrientation]; } - (void) SetUpScreen:(UIInterfaceOrientation)toInterfaceOrientation{ if (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft || toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) { self.Button.constant = (CGFloat)10; } else { self.Button.constant = (CGFloat)5; } [super updateViewConstraints]; } 

but I have no idea how to solve the problem with popover. I tried

 popoverController: willRepositionPopoverToRect: inView: 

but it just can't seem like it works.

Can anyone advise

thanks

+8
objective-c screen-orientation uipopover
source share
4 answers

In iOS 8, you can use - viewWillTransitionToSize: withTransitionCoordinator: to change the screen size (and orientation):

 - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator { [_popover dismissPopoverAnimated:NO]; [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context) { // Update your layout for the new size, if necessary. // Compare size.width and size.height to see if you're in landscape or portrait. } completion:^(id<UIViewControllerTransitionCoordinatorContext> context) { [_popover presentPopoverFromRect:[self popoverFrame] inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO]; }]; } 

When implementing this method, legacy rotation methods, such as willAnimateRotationToInterfaceOrientation: will not be called when running on iOS 8.

+4
source share

When using popoverController:willRepositionPopoverToRect:inView: when reassigning the rect parameter, try using:

 *rect = myNewRect; 

and not:

 rect = &presentingRect; 

Also, make sure you correctly assign the delegate to the popover controller.

+1
source share

First, you do not need to fire and submit a popover when spinning. The UIPopoverPresentationController does this for you. You do not even need to update sourceView / sourceRect after installing them when creating a popover.

Now the trick with animate(alongsideTransition: ((UIViewControllerTransitionCoordinatorContext) -> Void)?, completion: ((UIViewControllerTransitionCoordinatorContext) -> Void)? = nil) is that you should update your restrictions in closing alongsideTransition , and not in completion . This way you will make sure that the UIPopoverPresentationController has an updated sourceRect when restoring a popover at the end of the rotation.

What may seem contradictory is that inside the alongsideTransition closure you already have a new layout that you deduced from the constraint calculation.

Here is an example in Swift:

 override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) coordinator.animate(alongsideTransition: { _ in if self.popover != nil { // optionally scroll to popover source rect, if inside scroll view let rect = ... self.scrollView.scrollRectToVisible(rect, animated: false) // update source rect constraints myConstraint.constant = ... myConstrainedView.setNeedsLayout() myConstrainedView.layoutIfNeeded() } }, completion: nil) } 
0
source share

Very interesting - I got this to work without updating the position manually. I do not know why this works.

 let buttonContainer = UIView(frame: CGRectMake(0, 0, 44, 44)) let button = UIButton(frame: CGRectMake(0, 0, 44, 44)) buttonContainer.addSubview(button) view.addSubview(buttonContainer) popover!.presentPopoverFromRect(button, inView: button.superview!, permittedArrowDirections: .Any, animated: true) 

Place the button that the popover represents from inside the "container view". Then the popover will automatically change location when the orientation changes.

-one
source share

All Articles