Update for iOS 9 beta: Apple may have fixed this for iOS 9. If you work(ed) around this issue for iOS 8, make sure it also works correctly on iOS 9.
In storyboard, I've created a popover presentation segue to present a navigation and view controller from a button, as well as creating an unwind segue.
In portrait orientation, the modal (fullscreen) presentation is unwound/dismissed, as expected.
In landscape orientation, the unwind segue also gets called, however the popover presentation is not automatically dismissed.
Did I miss hooking something up? Do I have to dismiss the popover presentation myself?
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)__unused sender
{
if ([[segue identifier] isEqualToString:#"showSelectBookChapter"])
{
UINavigationController *navigationController = segue.destinationViewController;
if ([navigationController.topViewController isKindOfClass:[BIBLESelectViewController class]])
{
BIBLESelectViewController *selectViewController = (BIBLESelectViewController *)navigationController.topViewController;
selectViewController.initialBookChapterVerse = self.bookChapterVerse;
}
}
}
- (IBAction)unwindToBIBLEChapterViewController:(UIStoryboardSegue *)segue
{
if ([segue.identifier isEqualToString:#"unwindToBIBLEChapterViewController"]) {
if ([segue.sourceViewController isKindOfClass:[BIBLESelectViewController class]])
{
BIBLESelectViewController *sourceViewController = (BIBLESelectViewController *)segue.sourceViewController;
self.bookChapterVerse = sourceViewController.selectedBookChapterVerse;
[self.tableView reloadData];
}
}
}
Update:
After looking at gabbler's sample code, I've narrowed the problem down to popover dismissing fine in a Single View Application, but not in a Master-Detail Application.
Update 2:
Here's what the hierarchy looks like (omitting navigation controllers for simplicity's sake), in answer to the question Luis asked:
Split view controller
Master view controller
Detail view controller
Chapter view controller (modal page sheet)
Select view controller (the problematic popover that unwinds to chapter view controller, but doesn't dismiss)
As I mentioned in the previous update, I created an new master/detail template, and simply presented a popover directly from (a button in) the detail view. It won't dismiss.
I ran into this problem too. I present a View Controller modally (as a form sheet), from the Master View Controller (UISplitViewController). The problem only occurred on the iPad (probably the iPhone 6+ in landscape mode too, but I didn't check it). I ended up doing the following in my unwind action method (using Swift), and it works good.
if !segue.sourceViewController.isBeingDismissed() {
segue.sourceViewController.dismissViewControllerAnimated(true, completion: nil)
}
If you segue as a popover from a view controller embedded in a navigation controller, the corresponding unwind fails to dismiss the popover.
It's a bug in -[UINavigationController segueForUnwindingToViewController:fromViewController:identifier]. The embedding navigation controller is supposed to supply a segue that will dismiss the popover but it doesn't. The fix then is to override this and supply a working segue, which we can get from the embedded view controller.
Here's a partial solution that will only handle unwinding to the top view controller of the navigation stack:
#implementation MyNavigationController
- (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController
fromViewController:(UIViewController *)fromViewController
identifier:(NSString *)identifier
{
if (toViewController == self.topViewController && fromViewController.presentingViewController == self)
return [toViewController segueForUnwindingToViewController:toViewController
fromViewController:fromViewController
identifier:identifier];
else
return [super segueForUnwindingToViewController:toViewController
fromViewController:fromViewController
identifier:identifier];
}
#end
It works on iOS 8 for both landscape/portrait iPad and landscape/portrait iPhone. The logic should be robust enough to survive on iOS 9.
It is/must be a behavior of the popOver segue, in normal situations or regularly we need that the popOver keeps in view, if the segue show something important is annoying that we lost that information just because we rotate the device, I guess that that is the reason of that native behavior. So if we want for it to dismiss automaticly we have to make that behaivor by our own, this works:
in the method - (void)viewDidLoadin the detailViewController.m add this:
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter]
addObserver:self selector:#selector(orientationChanged:)
name:UIDeviceOrientationDidChangeNotification
object:[UIDevice currentDevice]];
then create this method:
- (void) orientationChanged:(NSNotification *)note{
UIDevice * device = note.object;
//CGRect rect = [[self view] frame];
switch(device.orientation)
{
default:
[self dismissViewControllerAnimated:YES completion:nil];
break; }}
You said that in a single view happens what you want, but I've never seen that behavior when I used popOvers.
mbeaty's fix is great but as others have pointed out, this bug seems to know be fixed in iOS 9 and it also doesn't work well for universal device design. I have adapted his answer to handle both situations. Here is the code:
#IBAction func yourUnwindSegue(segue: UIStoryboardSegue) {
if #available(iOS 9, *) {
return // bug fixed in iOS 9, just return and let it work correctly
}
// do the fix for iOS 8 bug
// access your SplitViewController somehow, this is one example
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let splitVC = appDelegate.window!.rootViewController as! YourSplitViewController
// if the source isn't being dismissed and the splitView isn't
// collapsed (ie both windows are showing), do the hack to
// force it to dismiss
if !segue.sourceViewController.isBeingDismissed() && splitVC.collapsed == false {
segue.sourceViewController.dismissViewControllerAnimated(true, completion: nil)
}
}
This first checks if iOS 9 is running and just exit as the bug seems to be fixed. This will prevent the multiple views getting dismissed issue. Also to make sure this fix is only done when the splitView is showing two windows (to make it happen only on iPads and iPhone 6 Plus in landscape as well as future devices) I added the check to make sure it is not collapsed.
I have not exhaustively check this but it seems to work. Also not that my app is set for a min of iOS 7, I don't know if this bug existed then so you may need to look into that if you support below iOS 8.
Related
I'm attempting a project using the Xcode (version 9.1 9B55) Master-Detail template, using one Storyboard for both iPhone and iPad.
I want to use the built in popover segue, which ideally will show a popover when the size class is appropriate, or a modal view controller when the size class is compact (iPhone in portrait).
What I am finding is that it works just fine for iPad, but when I run it on an iPhone, you can't touch outside the popover to dismiss as I would expect.
When on iPad, popoverPresentationControllerDidDismissPopover is called and all is well.
When on iPhone, the popoverPresentationControllerDidDismissPopover never gets called and you cannot dismiss the popover.
To reproduce, I did this:
Create new Master-Detail App
New - File. Cocoa Touch Class, called MyPopoverViewController
In Storyboard:
Create new view controller, change class to MyPopoverViewController.
On MasterViewController, add bar button item "Popover". Control-drag from this to MyPopoverViewController. Set segue Kind to "Present As Popover". Set Identifier to "thePopover".
In MasterViewController.h, add UIPopoverPresentationControllerDelegate:
#interface MasterViewController : UITableViewController <UIPopoverPresentationControllerDelegate>
In MasterViewController.m:
#import "MyPopoverViewController.h"
In viewDidLoad, comment out two lines which create the "Add Button".
In prepareForSegue:
} else if ([[segue identifier] isEqualToString:#"thePopover"]) {
NSLog(#"MVC prepareForSegue thePopover");
MyPopoverViewController *myPopoverController = segue.destinationViewController;
myPopoverController.popoverPresentationController.delegate = self;
}
Add three UIPopoverPresentationControllerDelegate delegate methods:
- (void) prepareForPopoverPresentation:(UIPopoverPresentationController *)popoverPresentationController {
NSLog(#"MVC prepareForPopoverPresentation");
}
- (void) popoverPresentationControllerDidDismissPopover:(UIPopoverPresentationController *)popoverPresentationController {
NSLog(#"MVC popoverPresentationControllerDidDismissPopover");
}
- (BOOL) popoverPresentationControllerShouldDismissPopover:(UIPopoverPresentationController *)popoverPresentationController {
NSLog(#"MVC popoverPresentationControllerShouldDismissPopover");
return TRUE;
}
I tried this also, but all it does is force popover in portrait mode (which I don't want); doesn't change the lack of popover delegate calls and doesn't allow us to dismiss popover:
-(UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller {
return UIModalPresentationNone;
}
I'm hoping there is something simple I'm missing here. I have uploaded a sample project here, which is exactly what I've described above:
https://github.com/johnstewart/MasterDetailPopoverTestProject
How do I allow iPhone to also dismiss popovers by touching outside the popover?
If I understand your question correctly your problem appears on iPhone 8 Plus in landscape mode.
In this situation, the presented popover actually is not a popover but a normal presented view. Visually it looks like a sheet that appears from the botton of the screen. In order to close such a view, you have to add your own button to do this.
If you want to show a real popover, you must implement:
adaptivePresentationStyleForPresentationController:traitCollection:
to return UIModalPresentationNone. Note the additional parameter traitcollection:. UIAdaptivePresentationControllerDelegate contains two similar methods. In your project you already implemented the method:
adaptivePresentationStyleForPresentationController:
Change this to the former method and everything should work.
This is my first post on SO, but I am very familiar with the site. I currently have an app that was working correctly until a recent iOS update. Here is the situation:
I have a PageViewController with a page that holds a TableViewController. When the phone orientation is changed from portrait to landscape, a modal view is created and presented to the user, using a modal segue. If the user then changes the orientation of the phone back to portrait, the app crashes.
I have spent many long hours trying to do work arounds and find/create solutions, but no luck. What I have discovered is "dismissViewControllerAnimated" is being called and the modal view is being deallocated. However, I have a print statement in at the beginning of my "orientationChanged" function. It prints once after the first time from landscape to portrait. But if the user rotates the phone to landscape again and back to portrait, "orientationChanged" will now be called twice, as though the view controller was never removed from the stack. If the user proceeds to do this 10 times, for example, on the 10th time "orientationChanged" will be called 10 times in a row.
This just doesn't make any sense to me. If the modal view is being deallocated, then how is this possible? Is there a copy of the modal view being stored somewhere? I tried to change the modal segue to be a push segue, but no luck. It would result in the same thing. Using the push segue and navigation bar that comes with it, I was able to navigate backwards through the view stack. The stack had duplicate copies of my desired modal view, like they were never removed from the stack, and at the bottom of the stack was my TableViewController.
Here is my orientationChanged function:
- (void)orientationChanged:(NSNotification *)notification
{
NSLog(popModalView ? #"Yes" : #"No");
NSLog(#"Index:%lu",(unsigned long)self.pageIndex);
UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
if (UIDeviceOrientationIsLandscape(deviceOrientation) && popModalView == NO)
{
[self performSegueWithIdentifier:#"DisplayGraphNumberOfJobs" sender:self];
popModalView = YES;
}
else if (UIDeviceOrientationIsPortrait(deviceOrientation) && popModalView == YES)
{
NSLog(#"dismiss");
[self dismissViewControllerAnimated:YES completion:nil];
popModalView = NO;
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"DisplayGraphNumberOfJobs"])
{
GraphJobTotalsVC *graphJobs = [segue destinationViewController];
//initialize graphJobs...
}
}
As a side note, my PageViewController has 3 pages, each with the same problem as this one. So solving one page should solve them all, hopefully. I have looked all over apple's documentation, but no luck. I have looked at countless other SO answers as well. I hope someone can help me. Thank you, in advance.
I have an app, that works fine under iOS 7, but when built for iOS 8 the unwind segues are not working.
I created a new project and added a modal (navigationcontroller with tableviewcontroller)and tried to use an unwind modal. Unfortunately it doesn't work either. The methods that are being unwind to, are in the desination view controller. The unwind segue is created through the storyboard (a Navigationbar button in the tableviewcontroller) When I tap the button, nothing happens. There is no log output and the modal does not disappear. It also only seems to affect modal segues. push/popover are unwound normally.
Has anyone had a similar problem and has an Idea how I could solve it?
Apple has FIXED this bug in iOS 8.1
Temporary solutions for iOS 8.0
The unwind segue will not work only in next situation:
View structure: UITabBarController -> UINagivationController -> UIViewController1 -> UIViewController2
Normally (in iOS 7, 8.1), When unwind from UIViewController2 to UIViewController1, it will call viewControllerForUnwindSegueAction in UIViewController1.
However in iOS 8.0 and 8.0.x, it will call viewControllerForUnwindSegueAction in UITabBarController instead of UIViewController1, that is why unwind segue no longer working.
Solution: override viewControllerForUnwindSegueAction in UITabBarController by create a custom UITabBarController and use the custom one.
For Swift
CustomTabBarController.swift
import UIKit
class CustomTabBarController: UITabBarController {
override func viewControllerForUnwindSegueAction(action: Selector, fromViewController: UIViewController, withSender sender: AnyObject?) -> UIViewController? {
var resultVC = self.selectedViewController?.viewControllerForUnwindSegueAction(action, fromViewController: fromViewController, withSender: sender)
return resultVC
}
}
For old school Objective-C
CustomTabBarController.h
#import <UIKit/UIKit.h>
#interface CustomTabBarController : UITabBarController
#end
CustomTabBarController.m
#import "CustomTabBarController.h"
#interface CustomTabBarController ()
#end
#implementation CustomTabBarController
-(UIViewController *)viewControllerForUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender
{
return [self.selectedViewController viewControllerForUnwindSegueAction:action fromViewController:fromViewController withSender:sender];
}
#end
==============================================================================
DO NOT USE ANY SOLUTIONS BELOW THIS POINT (they are out of date and just for reference)
Latest update on Sep 23
My new solution is pushing to a view that embedded in a navigation controller, and config that navigation controller to hide bottom bar on push(a tick box in IB). Then you will have a view looks like a modal view, the only different is the animate of pushing and popping. You can custom if you want
Updated: The solution below actually present the modal view under the tab bar, which will cause further view layout problems.
Change the segue type to Present As Popover will work only on iOS8 for iPhones, on iOS7 your app will crash.
Same here, to fix this, I set segue's presentation to current context(my app is for iphone only).
Default and full screen will not work.
[UPDATE: Bug fixed on iOS 8.1 beta but you'll need it for 8.0 and 8.0.2 support]
The only way I could make my unwind segue work was by mixing Aditya's and viirus' answers.
My setup going in:
[View Controller 1] > custom modal segue > [Navigation Controller] > root > [View Controller 2]
Unwind:
[View Controller 2] > custom unwind segue > [View Controller 1]
Fix:
Subclass the [Navigation Controller], add a property called sourceViewController and pass "self" to that property when prepare for segue is called when going from [View Controller 1] to [Navigation Controller]
In the [Navigation Controller] subclass .m override/add this two methods:
- (UIViewController *)viewControllerForUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender
{
if ([self.sourceViewController canPerformUnwindSegueAction:action fromViewController:fromViewController withSender:sender]) {
return self.sourceViewController;
}
return [super viewControllerForUnwindSegueAction:action fromViewController:fromViewController withSender:sender];
}
Then I override this in that [Navigation Controller] subclass only because I have a custom unwind segue:
- (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(NSString *)identifier {
return [fromViewController segueForUnwindingToViewController:toViewController
fromViewController:fromViewController
identifier:identifier];
}
This is a problem with iOS 8.0, 8.0.1, and 8.0.2. It was resolved in 8.1; unwind segues are calling the appropriate method now.
Note that on iOS 8, modally presented view controllers may not be automatically dismissed when performing an unwind segue, unlike iOS 7. To ensure it's always dismissed, you may detect if it's being dismissed and if not then manually dismiss it. These inconsistencies are resolved in iOS 9.0.
With iOS 8.4 running on iPhone, all of the modally presented segues with all presentation styles do dismiss upon unwind, except Over Full Screen and Over Current Context. That's also the case for iPad, with the addition of Form Sheet and Page Sheet also not auto-dismissing. With iOS 9, all presentation styles auto dismiss on both iPhone and iPad.
Yep it kinda happen to me too, I think for your case you have to subclass the UINavigationController and override the following:
- (UIViewController *)viewControllerForUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender
{
for(UIViewController *vc in self.viewControllers){
// Always use -canPerformUnwindSegueAction:fromViewController:withSender:
// to determine if a view controller wants to handle an unwind action.
if ([vc canPerformUnwindSegueAction:action fromViewController:fromViewController withSender:sender])
return vc;
}
return [super viewControllerForUnwindSegueAction:action fromViewController:fromViewController withSender:sender];
}
Same problem here. Unwind method is not called. Only happens when
using modal segue
Presentation is anything but "current context"
NavigationController is not extended (using default from storyboard)
Also happens in IOS8 GM Seed, therefore I think we need to find a workaround.
Sounds like a bug to me...
Extending UINavigationController and implementing viewControllerForUnwindSegueAction didn't help, as it is not fired. The only thing which gets fired is canPerformUnwindSegueAction() within the extended UINavigationController. Strange.
Woah there! I'm still getting user reports of getting stuck on a modal view in iOS 8.1.1 (on an iPad 3).
I'm jettisoning all this unwind from a modal view stuff. Just a good old-fashioned...
[self dismissViewControllerAnimated:NO completion:nil];
...works fine on all those various iOS 8.x.x versions.
It seems that both iOS 7.1 and iOS 8.1/8.2 create unwind segue from navigation controller however unwind segue is registered on a child controller inside of navigation controller.
So manually creating an unwind segue from the controller where it's registered in storyboard solves the problem.
#implementation RootNavigationController
- (UIStoryboardSegue*)segueForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(NSString *)identifier {
return [toViewController segueForUnwindingToViewController:toViewController fromViewController:fromViewController identifier:identifier];
}
#end
I encountered the same problem when unwinding to a source view controller from a destination view controller. The destination was presented through a "show" segue from the source.
I was using iPhone simulator that shows iPhone 6, iOS8.3.
XCode 6.3.2
The solution of subclassing NavigationViewController worked for me. Here is the swift code which is essentially swift translation of Raul's answer. I am puzzled that if Apple has fixed it in iOS8.1 per Raul, how am I getting hit by it in 8.3.
var sourceViewController: UIViewController?
override func viewControllerForUnwindSegueAction(action: Selector, fromViewController: UIViewController, withSender sender: AnyObject?) -> UIViewController? {
if(self.sourceViewController! .canPerformUnwindSegueAction(action, fromViewController: fromViewController, withSender: sender!)){
return self.sourceViewController
}
return super.viewControllerForUnwindSegueAction(action, fromViewController: fromViewController, withSender: sender)
}
I just ran into this problem, and after some digging discovered that with modal segues (at least ones with the default and fullscreen presentation modes), you can't rely on the normal unwind mechanism, but rather you have to call the presented UIViewController's dismissViewControllerAnimated method.
Steps to be followed:
Link the unwind segue to the button in Storyboard.
Create IBAction for the button and add the below code in it:
[self dismissViewControllerAnimated:NO completion:nil];
This should work for all versions.
With iPad with iOS6, we have this bug where a modal view controller will expand to full screen, even if it is told to
be using "form sheet" presentation style. But, this happens only if there are two modals, a parent one and its child.
So this is how the first modal is created and presented:
UINavigationController *navigationController = [[[UINavigationController alloc] initWithRootViewController:controller] autorelease];
navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
[parentController presentModalViewController:navigationController animated:YES];
// parentController is my application's root controller
This is how the child modal is created and presented:
UINavigationController *navigationController = [[[UINavigationController alloc] initWithRootViewController:controller] autorelease];
navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
[parentController presentModalViewController:navigationController animated:YES];
// parentController is the navigationController from above
So when rotating from landscape to portrait, the parent modal will expand to full screen and remain that way even if we rotate back to landscape.
When we have the parent modal all by itself (no child modal), then it works as expected, which is that it remains in form sheet style.
Note that this happens on iOS6 only (device and simulator) and doesn't happen on iOS 5 (simulator and reported to work by testers).
So far, I have tried the following without success:
setting wantsFullScreenLayout to NO
forcing wantsFullScreenLayout to always return NO by overriding it
Making certain my controllers inside the navigation controller also specify UIModalPresentationFormSheet
implementing preferredInterfaceOrientationForPresentation
upgrade to iOS 6.0.1
Thanks!
UPDATE:
So, I adapted the response from the Apple Developer Forums (https://devforums.apple.com/message/748486#748486) so that it works with multiple nested modal.
- (BOOL) needNestedModalHack {
return [UIDevice currentDevice].systemVersion.floatValue >= 6;
}
- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {
// We are the top modal, make to sure that parent modals use our size
if (self.needNestedModalHack && self.presentedViewController == nil && self.presentingViewController) {
for (UIViewController* parent = self.presentingViewController;
parent.presentingViewController;
parent = parent.presentingViewController) {
parent.view.superview.frame = parent.presentedViewController.view.superview.frame;
}
}
[super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
}
- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
duration:(NSTimeInterval)duration {
// We are the top modal, make to sure that parent modals are hidden during transition
if (self.needNestedModalHack && self.presentedViewController == nil && self.presentingViewController) {
for (UIViewController* parent = self.presentingViewController;
parent.presentingViewController;
parent = parent.presentingViewController) {
parent.view.superview.hidden = YES;
}
}
[super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
}
- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
// We are the top modal, make to sure that parent modals are shown after animation
if (self.needNestedModalHack && self.presentedViewController == nil && self.presentingViewController) {
for (UIViewController* parent = self.presentingViewController;
parent.presentingViewController;
parent = parent.presentingViewController) {
parent.view.superview.hidden = NO;
}
}
[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];
}
Not sure if this should be considered as a bug and I'm curious what iOS 7 will bring, but the current workaround for this issue is to set modalPresentationStyle to UIModalPresentationCurrentContext for the child-viewController.
Set modalPresentationStyle = UIModalPresentationCurrentContext
This makes the child still beeing presented as FormSheet but prevents the parent from beeing resized to fullscreen on rotation.
Dirk
I can see 2 problems here.
1) in iOS 6 the method presentModalViewController:animated: is deprecated, try using presentViewController:animated:completion:
(despite this might not help, you still may want to do it)
2) In iOS 6 somehow appeared that container controllers (such as UINavigationController) don't resend the autorotate messages to their children. Try subclassing the UINavigationController and redefine the corresponding autorotation methods to be sent to all of the children. This might help.
You need to instanciate your navigation controller after your main view.
So that you will be able to manage rotation in each view.
If your AppDelegate RootViewController is a navigation controller, you will not be able to manage rotation with native functions.
I have a couple of modal views that have been working "just fine" and now stopped returning to the parent view controller and "the code has not changed." -- classic problem description.
I debugged the modal view dismissing and the parent view controller is nil, which explains the problem, but not the cause. I did upgrade my SDK from 4.1.2 to 4.2 so I can start working with iOS 5. I am suspect of the new memory management ARC and my style of autorelease versus retain/release.
Following is the code from my rootview controller to the AboutViewController:
- (IBAction)doInfo:(id)sender {
NSLog(#"%s", __FUNCTION__);
AboutViewController *aboutViewController = [[[AboutViewController alloc] initWithNibName:#"AboutViewController" bundle:[NSBundle mainBundle]] autorelease];
if (aboutViewController) {
aboutViewController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
aboutViewController.hidesBottomBarWhenPushed = YES;
self.navigationController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
self.navigationController.navigationBarHidden = YES;
[self presentModalViewController:aboutViewController animated:YES];
}
}
Following is the dismiss in the AboutViewController back to its parent after pressing a "Done" button.
- (IBAction)doDone:(id)sender {
NSLog(#"%s", __FUNCTION__);
[[self parentViewController] dismissModalViewControllerAnimated:YES];
}
OK ... I fixed by changing as follows. Now the question is why did this work before?
- (IBAction)doDone:(id)sender {
NSLog(#"%s", __FUNCTION__);
[self dismissModalViewControllerAnimated:YES];
}
Quoting from [1] about the property parentViewController:
Prior to iOS 5.0, if a view did not have a parent view controller and was being presented modally, the view controller that was presenting it would be returned. This is no longer the case. You can get the presenting view controller using the presentingViewController property.
So this resolves the issue why this did work before and does not anymore. If building for iOS 5, I would use the presentingViewController property, as it is advised by the docs to let the parent view controller (or in this case presenting) dismiss the modal view. However if building for iOS 4 and 5, I would let your code in place as it forwards the call to the appropriate view controller anyway.
If in any case the app ran flawlessly on iOS 5 before recompiling, I would assume that Apple put some runtime-trickery in place that mimics the old behaviour for apps compiled pre-iOS5.
[1] http://developer.apple.com/library/ios/#documentation/uikit/reference/UIViewController_Class/Reference/Reference.html
I have built a category that add presentingViewController on iOS 4.
It disables itself on iOS 5.
You can use it seamlessly. Please see backward-modal.
I hope this benefits you as much as it does to me; It makes your code more clean!