I'm stumped :-\
I have a legacy app in the store that I'm refreshing for iOS 8/9. It was written years ago (pre-ARC) and is a universal app for iPhone and iPad. Everything is now working apart from this ...
On iPad, there is a toolbar at the top of the screen from which I present UIPopoverControllers containing a UINavigationController containing some standard UITableViewController type screens you can drill down into.
In Portrait (and Portrait Upside Down) everything works as expected.
In Landscape however, pressing 'Back' (the standard back not a custom one) causes weird animations - the outgoing controller jumps outside the popover and rapidly slides offscreen (the direction being governed by which orientation the device is in) while the incoming controller simply appears instantly as soon as the outgoing controller jumps outside the popover. I had to use slow animations to determine this as at full speed it just looks like a huge glitch.
There's a short 20 second movie showing the defect here; Note what happens when tapping 'Locations' at 14 seconds in.
If, instead of a UIPopover, I present the VC stack as a form sheet, everything works as expected regardless of orientation. I've also tried the newer UIPopoverPresentationController and experienced the SAME problem, which surprised me a little.
This happens on both of the popovers I'm presenting (one from left of toolbar, one from right of toolbar) and they both have very different internals. The only common factor is that they have a UINavigationController inside a UIPopover.
I've used the view debugger to inspect the view hierarchy, but nothing seems out of the ordinary and I can't capture the view during the glitch no matter how slow I run the simulator so I suspect I'm seeing an internal issue with the popover or navigation controller.
Has anyone seen anything similar? I see this both on-device (iOS 8.4) and in Simulators for iOS 8 and 9.
For context, this project has no storyboards, rarely uses xibs and generally constructs the UI in code within loadView - it really is an old application...
Thanks for any pointers. Not sure how much any code will help here, but here's the presentation of the popover concerned;
LocationsViewController* locationsvc = [[LocationsViewController alloc] init];
UINavigationController *localNavigationController = [[UINavigationController alloc] initWithRootViewController:locationsvc];
localNavigationController.navigationBar.barStyle = UIBarStyleBlackTranslucent;
[locationsvc release];
UIPopoverController* aPopover = [[UIPopoverController alloc] initWithContentViewController:localNavigationController];
aPopover.delegate = self;
aPopover.backgroundColor = [UIColor colorWithWhite:0 alpha:0.9];
self.locationPopoverController = aPopover;
[aPopover release];
[localNavigationController release];
[locationPopoverController presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
I get the same defect with the following, new flavour code;
UINavigationController *destNav = [[UINavigationController alloc] initWithRootViewController:locationsvc];
locationsvc.preferredContentSize = CGSizeMake(320,280);
UIPopoverPresentationController *newPresentationController;
destNav.modalPresentationStyle = UIModalPresentationPopover;
newPresentationController = destNav.popoverPresentationController;
newPresentationController.barButtonItem = sender;
destNav.navigationBarHidden = NO;
[self presentViewController:destNav animated:YES completion:nil];
And the same problem shows when I use UIModalPresentationPageSheet but NOT when I use UIModalPresentationFormSheet.
I had the same issue. The issue was fixed after I added support of landscape orientation to view controllers inside the navigation controller.
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskAll;
}
Related
I'm working on an iOS app which has a couple of non-modal views and a couple of modal views. The non-modal views have a navigation bar at the top, while the modal ones don't. The problem is that there's a common background image for both types. On the modal views, due to the lack of the navigation bar at the top, there's a small gap between the bottom of the image and the bottom of the display.
Here's the code for the opening of a non-modal display:
settingsController = [[SettingsController alloc] init];
settingsController.appState = appState;
[self.navigationController pushViewController:settingsController animated:YES];
[settingsController release];
Here's the code for the opening a modal display:
nextLevelViewController = [[[NextLevelViewController alloc] init] autorelease];
[self presentModalViewController: nextLevelViewController animated:YES];
What's the best way to have the background make up that gap at the bottom of the image?
Ok, I got it. It was just a question of modifying the view size to be a bit longer, then stretching the image to match it, in the xlb display editor.
I have a view that I wish to present to the user in the standard way (sliding up from the bottom of the screen). About half this view is a transparent background and the bottom half has some input fields (imagine the way the keyboard pops up). When I call [self presentViewController] on the rootViewController, it slides the view up, but then about half a second later, where the view used to be transparent it is replaced with black instead. This happens with both presentViewController and presentModalViewController. How to change this behaviour?
This is possible, and rockybalboa provides a solution to this issue in the forum post on raywenderlich.com:
iOS 8 UIModalPresentationCurrentContext is not transparent?
That solution being, quoting balboa's answer, in Objective-C:
Before iOS 8, you do this:
[backgroundViewController setModalPresentationStyle:UIModalPresentationCurrentContext];
[backgroundViewController presentViewController:_myMoreAppsViewController animated:NO completion:nil];
in iOS 8, you have to do this:
backgroundViewController.providesPresentationContextTransitionStyle = YES;
backgroundController.definesPresentationContext = YES;
[overlayViewController setModalPresentationStyle:UIModalPresentationOverCurrentContext];
To supplement the above code with the Swift equivalent:
backgroundViewController.providesPresentationContextTransitionStyle = true
backgroundController.definesPresentationContext = true
overlayViewController.modalPresentationStyle = .OverCurrentContext
Having implemented this using Xcode 6.3 beta 3 on iOS 8.1 with Swift 1.2, it works perfectly.
Just a comment that I viewed three different SO questions on this - the more recent now marked as duplicates - prior to finding and attempting the Ray Wenderlich forum solution.
As far as I know, transparent background is not supported when you presents a model view controller. Try retain the controller in your root view controller and simply add subview to the root view controller.
In the end, it looks like it's not possible for it to be transparent, I've got around this by adding this view as a subview outside of the bounds of the root view controller, and then slid it into place using an animation block. Not a lot of extra code, but it would have been nice to be able to use standard iOS behaviour to do it.
I had a similar problem with the black background appearing after a short delay when creating the controller with
Disclaimer *vc = [[Disclaimer alloc]init];
What solved the problem for me was to create a corresponding object in IB and instantiate the viewcontroller using it's storyboard ID:
Disclaimer *vc = (Disclaimer *)[self.storyboard instantiateViewControllerWithIdentifier:#"SBIDDisclaimer"];
[self presentViewController:vc animated:YES completion:nil];
I guess doing it via IB does some additional initialisations.
Using SWIFT 4, just add this code to the view controller you want to have a transparent background.
override func viewDidLoad()
{
super.viewDidLoad()
self.modalPresentationStyle = .overFullScreen
self.view.backgroundColor = UIColor.clear
}
I have an UIViewController(called MainViewController) which presents modally a semi-transparent view (HelpOverlayViewController):
HelpOverlayViewController *helpOverlayViewController = [[HelpOverlayViewController alloc] init];
self.modalPresentationStyle = UIModalPresentationCurrentContext;
helpOverlayViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:helpOverlayViewController animated:YES completion:nil];
If the user rotates the device while the HelpOverlayViewController is shown it only rotates HelpOverlayViewController and not the MainViewController i.e. the parent controller. This is a problem since HelpOverlayViewController is semi-transparent and MainViewController is visible below it.
Both controllers have the method
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
They both rotate fine independently.
Is there some way I can force the underlaying view controller to rotate when the modal view does?
I do know that issues like this will likely be largely resolved with iOS 6 as it has a different model for handling rotations.
However, that doesn't help you now. You might be best off just making your HelpOverlay a UIView and not a UIViewController. You can add this semi-transparent view onto the top of your MainViewController (or any other). You can still create an animation (like a fade-in) when adding this subview to your view hierarchy. With this model, you'll no longer have any issues with rotations.
DESCRIPTION OF THE INTERFACE
In the detail view of a split view, a programmatically drawn button calls (when clicked) a popover showing a text linked to the button's title.
Here is an abstract of the IBAction method :
DefinitionsPopoverViewController *defPVC = [[DefinitionsPopoverViewController alloc] init];
defPVC.delegate = self;
defPVC.definition = aDefinition;
UIPopoverController *defPC = [[UIPopoverController alloc] initWithContentViewController:defPVC];
defPC.popoverContentSize = CGSizeMake(480.0, popoverHeight);
[defPC presentPopoverFromRect:sender.frame
inView:self
permittedArrowDirections:UIPopoverArrowDirectionDown
animated:YES];
defPC.delegate = self;
self.definitionPopover = defPC;
Content of the popover
The UIPopover contains a VC with a UIWebView.
BEHAVIOR
In iOS 5.0 SDK, the behavior is normal : the popover appears then is dismissed when I touch outisde the popover area.
In iOS 5.1 SDK, the popover appears normally. Once visible, links in the UIWebView are operating normally. But every touch outside the popover does not dismiss the popover. Application seems frozen. No warning and no bug in XCode 4.2/4.3.
For the moment, I decided to keep my app developped under SDK 5.0 waiting for a solution to this issue.
I am writing an iPad app that requires the user to enter names and addresses and would like to use ABNewPersonViewController as the interface. The documentation says that this view controller should only be used from within a navigation controller. Is there anyway I can use just the ABNewPersonViewController in a subview (with a navigation controller) without it taking over my whole screen? I assume I can do this easily enough in a popover but I would prefer to have it integrated into my interface... Thanks for any help you can provide!
Consider presenting your UINavigationViewController by presentModalViewController:animated: and change modalViewPresentationStyle to UIModalPresentationPageSheet.
See the reference : http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html
Well, after much looking into this, it does not see that there is any way to use the address book UIs in a subview but they do work quite well in a popover view. However, this popover needs to be exactly 320x460 pixels or some other number with the same aspect ratio for the "add photo" to work correctly (otherwise the photo is stretched). In the popover's view controller viewDidLoad method I added:
self.picker = [[[ABNewPersonViewController alloc] init] autorelease];
self.picker.newPersonViewDelegate = self;
self.navigationController = [[[UINavigationController alloc] initWithRootViewController:self.picker] autorelease];
self.navigationController.view.frame = CGRectMake(0.0, 0.0, self.view.frame.size.width, self.view.frame.size.height);
[self.view addSubview:self.navigationController.view];
This seems to work fine. Let me know if you know of something better.