For my iPad app, I have a view displayed modally as a formsheet when a button is pushed. In order to have the keyboard dismissed after entering text in a textfield i tried as suggested;
the "disablesAutomaticKeyboardDismissal" method.
This does not work, in fact, the method is never called acording to the log.
The keybord will dismiss for iPhone or when i choose to not present modally.
Here is my code:
- (BOOL)disablesAutomaticKeyboardDismissal
{
NSLog(#"method calls");
return NO;
}
- (IBAction)showNewView:(id)sender
{
MyViewController *mvc =
[[MyViewController alloc] init];
// some lines about setting content
//...
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:mvc];
[navController setModalPresentationStyle:UIModalPresentationFormSheet];
[self presentViewController:navController animated:YES completion:nil];
}
-(BOOL)disablesAutomaticKeyboardDismissal
or not, the keyboard is not dismissed unless i remove tis line:
// [navController setModalPresentationStyle:UIModalPresentationFormSheet];
However, then it is not presented the way I want anymore.
Can anyone see what I am doing wrong?
-(BOOL)disablesAutomaticKeyboardDismissal needs to overridden to return NO by the view controller that is presented as a form sheet, not by the presenter; That's your mistake. In your case you could subclass UINavigationController to get the desired behaviour:
#interface AutomaticKeyboardDismissingNavigationController : UINavigationController
#end
#implementation AutomaticKeyboardDismissingNavigationController
- (BOOL)disablesAutomaticKeyboardDismissal
{
return NO;
}
#end
(The class name could probably be a bit shorter and still be comprehensible.)
Related
I am using AddressBookUI Framework for Adding contact, when I tried to pushing this view controller then cancel and done button not working properly, I don't want to present it
Here is my code
ABNewPersonViewController *abnpvc = [[ABNewPersonViewController alloc] init];
[abnpvc setNewPersonViewDelegate: self];
[self.navigationController pushViewController:abnpvc animated:YES];
I am also tried add as subview rather then pushing it but when I am adding as subview then it was not added
As per comment i have tried like
UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:abnpvc];
[self presentViewController:navigation animated:YES completion:nil];
Can anyone help me out why properly not working ?
You can implement that too considering also the other answers and the deprecations to ABNewPersonViewController in iOS 9.
As per your remarks:
cancel and done button not working properly
They are working if you have included the ABNewPersonViewControllerDelegate on interface like this:
#interface ViewController () <ABNewPersonViewControllerDelegate>
Pushing the viewController on navigation stack like this:
ABNewPersonViewController *controller = [[ABNewPersonViewController alloc] init];
controller.newPersonViewDelegate = self;
[self.navigationController pushViewController:controller animated:YES];
And by conforming to the protocol by implementing this method:
- (void)newPersonViewController:(ABNewPersonViewController *)newPersonView didCompleteWithNewPerson:(nullable ABRecordRef)person {
// Trick to go back to your view by popping it from the navigation stack when done or cancel button is pressed
[self.navigationController popViewControllerAnimated:YES];
}
The tricky line is to pop the newPersonController from the navigation stack when either Done or Cancel button are pressed.
Enjoy it
Why can't you just do it as the docs say?
It is recommended that you present a new-person view controller modally.
Use
ABNewPersonViewController *abnpvc = [[ABNewPersonViewController alloc] init];
[abnpvc setNewPersonViewDelegate: self];
[self presentViewController:abnpvc animated:YES completion:nil];
That should work fine.
Edit
On second thought, did you set your delegate correctly and do the implementations get called? I suspect they are not implemented or the delegate is not set correctly.
Apple guideline(IMPORTANT) :: New-person view controllers must be used with a navigation controller in order to function properly. It is recommended that you present a new-person view controller modally.
Add Delegate
#interface ViewController () <ABNewPersonViewControllerDelegate>
Pushing the viewController
ABNewPersonViewController *abnpvc = [[ABNewPersonViewController alloc] init];
[abnpvc setNewPersonViewDelegate: self];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:abnpvc];
[self presentModalViewController:navController animated:YES];
And Now Add Delegate Method
#pragma mark ABNewPersonViewControllerDelegate methods
- (void)newPersonViewController:(ABNewPersonViewController *)newPersonViewController didCompleteWithNewPerson:(ABRecordRef)person
{
[self dismissViewControllerAnimated:YES completion:NULL];
}
That will work fine.
I've discovered that after dismissing a modal view controller that's presented fullscreen in a compact view and as a popover in a horizontally regular view, the screen goes black after the animation.
My View Hierarchy is the following
View (of my rootViewController on the window)
--->UISplitViewController.view ( set as a child viewController )
--------> rootViewController.view (set as the mainViewController of the splitView)
--------> detailViewController.view (set as the detailViewController of the split view)
Via the iPhone 6 simulator(split view is always collapsed) I present a modal viewcontroller with the following code:
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
[navigationController.navigationBar setBarStyle:UIBarStyleBlack];
[navigationController setModalPresentationStyle:UIModalPresentationPopover];
navigationController.popoverPresentationController.sourceView = view;
navigationController.popoverPresentationController.barButtonItem = barButtonItem;
navigationController.popoverPresentationController.delegate = self;
[self presentViewController:nav animated:YES completion:nil];
I dissmiss the presented controller from that viewController by calling:
[self dismissViewControllerAnimated:true completion:nil];
If I set animated to "false" I dont have any problems, but it looks bad and doesnt make sense.
I see some posts regarding this and custom presenatation methods, but I'm not using anything custom here.
On iPhone the ModalPresentationStyle should default to UIModalPresentationOverFullScreen, so I tried setting the presentationStyle directly to that, and it worked!
If I set the presentationStyle to "FullScreen" (not over fullscreen) I get the same behavior, a black screen after dismissing.
Any thoughts or experiences on this one?
I've come up with the following work around, but I still don't think it should be needed.
- (UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller traitCollection:(UITraitCollection *)traitCollection{
if( traitCollection.horizontalSizeClass == UIUserInterfaceSizeClassCompact )
{
return UIModalPresentationOverFullScreen;
}
else
{
return UIModalPresentationPopover;
}
}
I want to recreate the search UI shown in the iOS 7/8 calendar app. Presenting the search UI modally isn't a problem. I use UISearchController and modally present it just like the UICatalog sample code shows which gives me a nice drop down animation. The issue comes when trying to push a view controller from the results view controller. It isn't wrapped in a navigation controller so I can't push onto it. If I do wrap it in a navigation controller then I don't get the default drop down animation when I present the UISearchController. Any ideas?
EDIT:
I got it to push by wrapping my results view controller in a nav controller. However the search bar is still present after pushing the new VC onto the stack.
EDIT (2):
DTS from Apple said that the calendar app uses a non-standard method to push from search results. Instead they recommend removing focus from the search controller then pushing and returning focus on pop. This is similar to the way search in the settings app works I imagine.
Apple has gotten very clever there, but it's not a push, even though it looks like one.
They're using a custom transition (similar to what a navigation controller would do) to slide in a view controller which is embedded in a navigation controller.
You can spot the difference by slowly edge-swiping that detail view back and letting the previous view start to appear. Notice how the top navigation slides off to the right along with the details, instead of its bar buttons and title transitioning in-place?
Update:
The problem that you're seeing is that the search controller is presented above your navigation controller. As you discovered, even if you push a view controller onto a navigation controller's stack, the navigation bar is still beneath the search controller's presentation, so the search bar obscures any (pushed view controller's) navigation bar.
If you want to show results on top of the search controller without dismissing it, you'll need to present your own modal navigation view controller.
Unfortunately, there's no transition style which will let you present your navigation controller the same way the built-in push animation behaves.
As I can see, there are three effects that need to be duplicated.
The underlying content dims, as the presented view appears.
The presented view has a shadow.
The underlying content's navigation completely animates off-screen, but its content partially animates.
I've reproduced the general effect within an interactive custom modal transition. It generally mimic's Calendar's animation, but there are some differences (not shown), such as the keyboard (re)appearing too soon.
The modal controller that's presented is a navigation controller. I wired up a back button and edge swipe gesture to (interactively) dismiss it.
Here are the steps that are involved:
In your Storyboard, you would change the Segue type from Show Detail to Present Modally.
You can leave Presentation and Transition set to Default, as they'll need to be overridden in code.
In Xcode, add a new NavigationControllerDelegate file to your project.
NavigationControllerDelegate.h:
#interface NavigationControllerDelegate : NSObject <UINavigationControllerDelegate>
NavigationControllerDelegate.m:
#interface NavigationControllerDelegate () <UIViewControllerTransitioningDelegate>
#property (nonatomic, weak) IBOutlet UINavigationController *navigationController;
#property (nonatomic, strong) UIPercentDrivenInteractiveTransition* interactionController;
#end
- (void)awakeFromNib
{
UIScreenEdgePanGestureRecognizer *panGestureRecognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
panGestureRecognizer.edges = UIRectEdgeLeft;
[self.navigationController.view addGestureRecognizer:panGestureRecognizer];
}
#pragma mark - Actions
- (void)handlePan:(UIScreenEdgePanGestureRecognizer *)gestureRecognizer
{
UIView *view = self.navigationController.view;
if (gestureRecognizer.state == UIGestureRecognizerStateBegan)
{
if (!self.interactionController)
{
self.interactionController = [UIPercentDrivenInteractiveTransition new];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
}
else if (gestureRecognizer.state == UIGestureRecognizerStateChanged)
{
CGFloat percent = [gestureRecognizer translationInView:view].x / CGRectGetWidth(view.bounds);
[self.interactionController updateInteractiveTransition:percent];
}
else if (gestureRecognizer.state == UIGestureRecognizerStateEnded)
{
CGFloat percent = [gestureRecognizer translationInView:view].x / CGRectGetWidth(view.bounds);
if (percent > 0.5 || [gestureRecognizer velocityInView:view].x > 50)
{
[self.interactionController finishInteractiveTransition];
}
else
{
[self.interactionController cancelInteractiveTransition];
}
self.interactionController = nil;
}
}
#pragma mark - <UIViewControllerAnimatedTransitioning>
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)__unused presented presentingController:(UIViewController *)__unused presenting sourceController:(UIViewController *)__unused source
{
TransitionAnimator *animator = [TransitionAnimator new];
animator.appearing = YES;
return animator;
}
- (id<UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)__unused dismissed
{
TransitionAnimator *animator = [TransitionAnimator new];
return animator;
}
- (id<UIViewControllerInteractiveTransitioning>)interactionControllerForPresentation:(id<UIViewControllerAnimatedTransitioning>)__unused animator
{
return nil;
}
- (id<UIViewControllerInteractiveTransitioning>)interactionControllerForDismissal:(id<UIViewControllerAnimatedTransitioning>)__unused animator
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wgnu-conditional-omitted-operand"
return self.interactionController ?: nil;
#pragma clang diagnostic pop
}
The delegate will provide the controller with its animator, interaction controller, and manage the screen edge pan gesture to dismiss the modal presentation.
In Storyboard, drag an Object (yellow cube) from the object library to the modal navigation controller. Set its class to ourNavigationControllerDelegate, and wire up its delegate and navigationController outlets to the storyboard's modal navigation controller.
In prepareForSegue from your search results controller, you'll need to set the modal navigation controller's transitioning delegate and modal presentation style.
navigationController.transitioningDelegate = (id<UIViewControllerTransitioningDelegate>)navigationController.delegate;
navigationController.modalPresentationStyle = UIModalPresentationCustom;
The custom animation that the modal presentation performs is handled by transition animator.
In Xcode, add a new TransitionAnimator file to your project.
TransitionAnimator.h:
#interface TransitionAnimator : NSObject <UIViewControllerAnimatedTransitioning>
#property (nonatomic, assign, getter = isAppearing) BOOL appearing;
TransitionAnimator.m:
#implementation TransitionAnimator
#synthesize appearing = _appearing;
#pragma mark - <UIViewControllerAnimatedTransitioning>
- (NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
return 0.3;
}
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
// Custom animation code goes here
}
The animation code is too long to provide within an answer, but it's available in a sample project which I've shared on GitHub.
Having said this, the code, as it stands, was more of a fun exercise. Apple has had years to refine and support all their transitions. If you adopt this custom animation, you may find cases (such as the visible keyboard) where the animation doesn't do what Apple's does. You'll have to decide whether you want to invest the time to improve the code to properly handle those cases.
I know this thread is old, but there seems to be a much simpler approach to getting the desired behavior.
The important thing to realize is the UISearchController is presented from the source controller, which is a view controller inside the navigation controller. If you inspect the view hierarchy, you see that the search controller, unlike regular modal presentations, isn't presented as a direct child of the window, but rather as a subview of the navigation controller.
So the general structure is
UINavigationController
MyRootViewController
UISearchViewController (presented pseudo-"modally")
MyContentController
Essentially you just need to get from the MyContentController up to the MyRootViewController, so you can access its navigationController property. In my tableView:didSelectRowAtIndexPath: method of my search content controller, I simply use the following to access my root view controller.
UINavigationController *navigationController = nil;
if ([self.parentViewController isKindOfClass:[UISearchController class]]) {
navigationController = self.parentViewController.presentingViewController.navigationController;
}
From there you can easily push something onto the navigation controller, and the animation is exactly what you'd expect.
EDIT: an alternate solution that doesn't rely on a UIWindow. I think the effect is very similar to the calendar app.
#interface SearchResultsController () <UINavigationControllerDelegate>
#end
#implementation SearchResultsController
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// this will be the UINavigationController that provides the push animation.
// its rootViewController is a placeholder that exists so we can actually push and pop
UIViewController* rootVC = [UIViewController new]; // this is the placeholder
rootVC.view.backgroundColor = [UIColor clearColor];
UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController: rootVC];
nc.modalPresentationStyle = UIModalPresentationCustom;
nc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[UIView transitionWithView: self.view.window
duration: 0.25
options: UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionAllowAnimatedContent
animations: ^{
[self.parentViewController presentViewController: nc animated: NO completion: ^{
UIViewController* resultDetailViewController = [UIViewController alloc];
resultDetailViewController.title = #"Result Detail";
resultDetailViewController.view.backgroundColor = [UIColor whiteColor];
[nc pushViewController: resultDetailViewController animated: YES];
}];
}
completion:^(BOOL finished) {
nc.delegate = self;
}];
}
- (void) navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
// pop to root? then dismiss our window.
if ( navigationController.viewControllers[0] == viewController )
{
[UIView transitionWithView: self.view.window
duration: [CATransaction animationDuration]
options: UIViewAnimationOptionTransitionCrossDissolve | UIViewAnimationOptionAllowAnimatedContent
animations: ^{
[self.parentViewController dismissViewControllerAnimated: YES completion: nil];
}
completion: nil];
}
}
#end
ORIGINAL solution:
Here's my solution. I start out using the same technique you discovered in the UICatalog example for showing the search controller:
- (IBAction)search:(id)sender
{
SearchResultsController* searchResultsController = [self.storyboard instantiateViewControllerWithIdentifier: #"SearchResultsViewController"];
self.searchController = [[UISearchController alloc] initWithSearchResultsController:searchResultsController];
self.searchController.hidesNavigationBarDuringPresentation = NO;
[self presentViewController:self.searchController animated:YES completion: nil];
}
In my example, SearchResultsController is a UITableViewController-derived class. When a search result is tapped it creates a new UIWindow with a root UINavigationController and pushes the result-detail view controller to that. It monitors for the UINavigationController popping to root so it can dismiss the special UIWindow.
Now, the UIWindow isn't strictly required. I used it because it helps keep the SearchViewController visible during the push/pop transition. Instead, you could just present the UINavigationController from the UISearchController (and dismiss it from the navigationController:didShowViewController: delegate method). But modally-presented view controllers present on an opaque view by default, hiding what's underneath. You could address this by writing a custom transition that would be applied as the UINavigationController's transitioningDelegate.
#interface SearchResultsController () <UINavigationControllerDelegate>
#end
#implementation SearchResultsController
{
UIWindow* _overlayWindow;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// this will be the UINavigationController that provides the push animation.
// its rootViewController is a placeholder that exists so we can actually push and pop
UINavigationController* nc = [[UINavigationController alloc] initWithRootViewController: [UIViewController new]];
// the overlay window
_overlayWindow = [[UIWindow alloc] initWithFrame: self.view.window.frame];
_overlayWindow.rootViewController = nc;
_overlayWindow.windowLevel = self.view.window.windowLevel+1; // appear over us
_overlayWindow.backgroundColor = [UIColor clearColor];
[_overlayWindow makeKeyAndVisible];
// get this into the next run loop cycle:
dispatch_async(dispatch_get_main_queue(), ^{
UIViewController* resultDetailViewController = [UIViewController alloc];
resultDetailViewController.title = #"Result Detail";
resultDetailViewController.view.backgroundColor = [UIColor whiteColor];
[nc pushViewController: resultDetailViewController animated: YES];
// start looking for popping-to-root:
nc.delegate = self;
});
}
- (void) navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
// pop to root? then dismiss our window.
if ( navigationController.viewControllers[0] == viewController )
{
[_overlayWindow resignKeyWindow];
_overlayWindow = nil;
}
}
#end
As you present a viewController the navigationController becomes unavailable. So you have to dismiss your modal first and then push another viewController.
UISearchController must be rootViewController of a UINavigationController and then you present navigation controller as modal.
I am presenting a modal view controller on the iPad which changes the presenting view controller while presented. For example:
A view controller VC presents the modal view controller when the user selects a cell in a table view.
The user selects an item on the modal view controller and another VC instance is opened in place of the first. Importantly, the view controller instance replacing the first is of the same type.
The modal view controller cannot be dismissed or an EXC_BAD_ACCESS exception occurs.
The failing dismiss is understandable: the presenting view controller is no longer available. Basically, how would I dismiss this presented modal view controller from a different presenting view controller?
The code I already have is:
ViewController1.m
- (void)showModalViewController:(UIViewController *)viewController
{
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
viewController.navigationItem.rightBarButton = [[UIBarButton alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dismissModalViewController)];
[self presentViewController:navigationController animated:YES completion:nil];
}
- (void)dismissModalViewController
{
[self dismissViewControllerAnimated:YES completion:nil];
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
}
Thanks for your suggestions but I solved the issue by using delegation. The presented view controller defined a delegate to notify the presenter when an action occurred.
ChildViewControler.h:
#protocol ChildViewControllerDelegate <NSObject>
- (void) childView:(ChildViewController *)childView didSelectItem:(Item *)item;
#end
ChildViewController.m:
// in interface
#property (nonatomic, weak) id <ChildViewControllerDelegate> delegate;
// in implementation
- (void)closeView:(Item *)anItem
{
[self.delegate childView:self didSelectItem:anItem];
}
ViewController1.m:
- (void)showModalViewController:(UIViewController *)viewController
{
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
viewController.navigationItem.rightBarButton = [[UIBarButton alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dismissModalViewController)];
// Different view controller types may be passed here so check is required...
if (viewController.class == [ChildViewController class]) {
((ChildViewController *)viewController).delegate = self;
[self presentViewController:navigationController animated:YES completion:nil];
}
- (void)childView:(ChildViewController *)childView didSelectItem:(Item *)item
{
[self dismissViewControllerAnimated:YES completion:nil];
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
// Perform action required with 'item'
}
You can try to change
self.presentingViewController
(The view controller that presented this view controller or its farthest ancestor.)
property in your modal View Controller before dismissing.
Here is your problem:
//...
viewController.navigationItem.rightBarButton = [[UIBarButton alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dismissModalViewController)];
//...
- (void)dismissModalViewController
{
[self dismissViewControllerAnimated:YES completion:nil];
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
}
You try to dismiss presenter view controller (that is currently seems to be swithced to another already) instead of presented modal view controller (in your case it UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];)
so (if presenters view controllers not the tabs of tabViewController or not stored in navigationController's stack or somewhere else) you must to store reference to it somewhere else than in presenter view controller which will be switched and could be deallocated.
As per document presentingViewController is a readonly property.
You could not modify it.
#property(nonatomic,readonly) UIViewController *presentingViewController NS_AVAILABLE_IOS(5_0);
I have not tested this code but there may be error in dismissModalViewController.
please put break point on this method the first line is perfect may your second line may cause error,may self.tableView is not accessible or self.tableView indexPathForSelectedRow may be nil.
- (void)dismissModalViewController
{
[self dismissViewControllerAnimated:YES completion:nil];
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
}
Thanks.
I have now been stuck on this problem for more then 2 weeks! In my project, I have 1 single ViewController(slide) I want to enable both landscape and portrait in. The rest of all controllers/views(slides) I want to enable portrait-mode only.
The tricky part is, the "ViewController" I am referring to is connected to both NavigationControllers and TabBarControllers. See the scheme below where the ViewController I want to enable both landscape/portrait is named: ReferredViewController.
TabBarController ----> NavigationController ----> FristViewController --(push event)--> ReferredViewController
So far I have tried to make a CATEGORY for both NavigationControllers and TabBarControllers. But since my NavigationControllers and TabBarControllers are placed at the very start of the project this will set the rules for the whole project. My ReferredViewController is placed at the end or in the middle of the projects "storyboard". I have tried to set the rules by code aswell for the single ReferredViewController without any success.
My best shot is to change the event between FirstViewController and ReferredViewController from "push" to "modal". ReferredViewController can then rotate both portrait/landscape and the rest of the project is locked in portrait. BUT, as you may know all navigations (NavigationBar) will be lost and the user will become stuck at that single slide.
So I am trying to enable the NavigationBar with the following code example in the ReferredViewController.m file:
ShowTaskViewController *detailViewController = [[ShowTaskViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
navController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.navigationController presentModalViewController:navController animated:YES completion:nil];
[navController release];
[detailViewController release];
But ofc nothing happens and I am back to square one again :O. FML!
In this line:
[self.navigationController presentModalViewController:navController
animated:YES
completion:nil];
you are conflating two UIViewController instance methods:
- (void)presentViewController:(UIViewController *)viewControllerToPresent
animated:(BOOL)flag
completion:(void (^)(void))completion
- (void)presentModalViewController:(UIViewController *)modalViewController
animated:(BOOL)animated
The first of these is now the standard, the second method was deprecated in ios6.
Also the presenting view controller should be self (the ReferredViewController), not self's navigationController.
Your presented view controller can dismiss itself thus
[[self presentingViewController] dismissViewControllerAnimated:YES
completion:(void (^)(void))completion];
But take a look at fibnochi's answer, it may be a better way for you to achieve your result.
you have to over ride UITaBarController because it is you base view controller. I have done this for my navigation controller. Tell me if this helped.
#interface UINavigationController (Autorotation)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation;
- (BOOL) shouldAutorotate;
- (NSUInteger) supportedInterfaceOrientations;
#end
#implementation UINavigationController (Autorotation)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation{
if ([self.visibleViewController isKindOfClass:[MWPhotoBrowser class]] || [self.visibleViewController isKindOfClass:[ZoomPictureViewController class]]) {
return YES;
}
return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}
-(BOOL) shouldAutorotate{
return YES;
}
-(NSUInteger) supportedInterfaceOrientations{
if ([self.visibleViewController isKindOfClass:[MWPhotoBrowser class]] || [self.visibleViewController isKindOfClass:[ZoomPictureViewController class]]) {
return UIInterfaceOrientationMaskAll;
}
return UIInterfaceOrientationMaskPortrait;
}