Dismiss a Modal-Presented UITabBarController - objective-c

EDIT: Added code that contains the dismissal.
NEW DATA
The problem remains the same as the problem listed under old data, except the dismissal line has changed.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"Yes"])
{
NSLog(#"Calling Dismissal...");
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
}
}
The function is being called because "Calling Dismissal..." is displayed in the log.
Current Hierarchy: UITabBarController - NavigationController/NavigationController - View1/View2
OLD DATA
In case the question was confusing, I am trying to dismiss a UITabBarController than I presented modally. The UITabBarController does use NavigationControllers to setup the two views inside. However, no matter how many parentViewController s I put in
(i.e.):
[self.parentViewController.parentViewController.etc... dismissViewControllerAnimated:YES completion:nil];
The UITableBarController will not dismiss. I have a button being placed in the NavigationController of both views that is calling the line of code above. Any hints on how to dismiss the UITableViewController?

The presenting view controller, which is not the same concept as the parent view controller, needs to dismiss it. This code:
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
will typically do the trick.
However, depending on what this controller's function is, I usually prefer to have my presented controllers send a delegate message or NSNotification to the parent, so the parent can extract whatever data it needs before dismissal.

Related

ActionSheet pushViewController Problems

I am having problems presenting a view controller from an action sheet in iOS 7. My program just seems to skip over:
[self.navigationController presentViewController:viewController animated:TRUE];
Has anyone else encountered this problem?
Thanks.
self.navigationController is nil if the view controller is not embedded inside a navigation controller. Sending a message to nil is ignored (which is why your program is skipping over that line).
Change self.navigationController to self, or self.tabBarController if you're using a tab bar controller, or self.splitViewController if you're using a split view controller.
try with
[self presentViewController:viewController animated:YES completion:nil];
Try present new view controller in - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex

dismiss presenting viewController is not working and a warning message is appeared

I have an issue with dismissing the current viewController and presenting another one. I have the current viewController named viewController3 with MKMapView. When I try to open another viewController from viewController3 a warning message says
"Warning: Attempt to present <ViewController3: 0xb84e270> on <ViewController2: 0xb8485e0> while a presentation is in progress!"
"attempt to dismiss modal view controller whose view does not currently appear. self = <ViewController2: 0xb8485e0> modalViewController = <ViewController3: 0x9b55130>"
update :
this warning is also shown
"Warning: Attempt to present <ViewController4_modified: 0x9b79c70> on <ViewController3: 0xb18ebc0> whose view is not in the window hierarchy!"
here is the code in viewController3.m file
- (IBAction)testButton:(id)sender
{
ViewController4_modified *VC4 = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController4_modified"];
VC4.formUserNameTextInVC3 = self.mapUserNameTextInVC2;
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
NSLog(#"VC3 is dismissed");
[self presentViewController:VC4 animated:YES completion:nil];
}
I am also using the same code to go form viewController2 to viewController3.
Any help will be appreciated.
Thanks in Advance !
I found the solution.
instead of using:
[self dismissViewControllerAnimated:YES completion:nil];
use:
[[[self parentViewController] parentViewController] dismissViewControllerAnimated:YES completion:nil];
Your issue that you are dismissing a view at the same time loading a new view. What you should do is load the new view, after you have completed with the dismissal as such:
[self.presentingViewController dismissViewControllerAnimated:YES completion: ^{
NSLog(#"VC3 is dismissed");
[self presentViewController:VC4 animated:YES completion:nil];
}];
That way, it will dismiss the current controller, and then load the next one after it has completed.

Wrong 'presentingViewController'

In my MainViewController, I present another view controller through this:
MessageViewController *messageController = [[MessageViewController alloc]initWithNibName:nil bundle:nil];
[messageController setModalPresentationStyle:UIModalPresentationFullScreen];
[messageController setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self presentViewController:messageController animated:YES completion:nil];
[messageController release];
This will display the view controller correctly. However, when I try to go back to the presenting view controller, which in this case should be the MainViewController, this code doesn't work:
if ([self.presentingViewController isKindOfClass:[MainViewController class]])
[(MainViewController *)self.presentingViewController setCurrentViewTag:2];
[self dismissModalViewControllerAnimated:YES];
I removed the "if.." condition to force it in setting the current view tag. An error occurred telling me that the presenting view controller seems to be the UINavigationController:
[UINavigationController setCurrentViewTag:]: unrecognized selector sent to instance 0x8352a50
Can anyone tell me why is this happening? This code used to work before and I am not sure what changed to make it stop working properly.
EDIT
Here is the updated code:
ReaderController *readerController = [[ReaderController alloc]initWithNibName:nil bundle:nil];
[readerController loadWhichViewToShow:2];
[self setDefinesPresentationContext:YES];
[readerController setModalPresentationStyle:UIModalPresentationFullScreen];
[readerController setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self presentViewController:readerController animated:YES completion:nil];
[readerController release];
Calling [self presentViewController:messageController animated:YES completion:nil]; doesn't necessarily use the vc you call this on to present the other vc. By default it travels up the vc-hierarchy and presents the other vc on the root view controller. That's why in your case the presenting view controller is a UINavigationController.
If you want to force your MainViewController to be the presenting vc, you have call:
[self setDefinesPresentationContext:YES];
on your MainViewController before presenting the MessageViewController.
Edit: In case someone else reads this: definesPresentationContext seems to be bugged or the documentation is wrong. See the comments below and Cocoa Builder
copy of my answer from this question
from Programming iOS 6, by Matt Neuburg:
On the iPad, when the presented view controller’s modalPresentationStyle is UIModalPresentationCurrentContext, a decision has to be made as to what view controller should be the presented view controller’s presentingViewController. This will determine what view will be replaced by the presented view controller’s view. This decision involves another UIViewController property, definesPresentationContext (a BOOL). Starting with the view controller to which presentViewController:animated:completion: was sent, we walk up the chain of parent view controllers, looking for one whose definesPresentationContext property is YES. If we find one, that’s the one; it will be the presentingViewController, and its view will be replaced by the presented view controller’s view. If we don’t find one, things work as if the presented view controller’s modalPresentationStyle had been UIModalPresentationFullScreen.
TL;DR
1. set definesPresentationContext to true on the desired presentingViewController
2. set modalPresentationStyle to UIModalPresentationCurrentContext on the desired presentedViewController
If seems that you need to set three thing in iOS 11.
controller.modalPresentationStyle = UIModalPresentationCurrentContext;
controller.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
self.definesPresentationContext = YES;
[self presentViewController:controller animated:YES completion:nil];

Attempt to present * on * whose view is not in the window hierarchy

I'm trying to make a modal view controller in my app delegate (I created a function called showLoginView). But whenever I try to call it I get a warning in XCode:
Warning: Attempt to present <PSLoginViewController: 0x1fda2b40> on <PSViewController: 0x1fda0720> whose view is not in the window hierarchy!
Here's the method code:
- (void)showLoginView
{
PSLoginViewController *loginViewController = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:NULL] instantiateViewControllerWithIdentifier:#"PSLoginViewController"];
[self.window.rootViewController presentViewController:loginViewController animated:NO completion:nil];
}
How can I add the view to the window hierarchy? Or maybe I'm doing something very wrong?
You can't display a modal view controller from the appDelegate. You need to display a modal ViewController from whichever viewController is currently displaying full-screen. In other words, you need to put that code into your root view controller, or whichever one you want to display the modal vc from...
Also, you'll want to use the method "presentModalViewController" to present the modal. You can set properties on the modal vc such as:
vC.modalPresentationStyle = UIModalPresentationFormSheet;
vC.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:vC animated:YES];
You can actually present a modal view Controller from the AppDelegate as long as you detect the current visible viewController and take care of the case where you current controller is a navigationController.
Here is what I do:
UIViewController *activeController = [UIApplication sharedApplication].keyWindow.rootViewController;
if ([activeController isKindOfClass:[UINavigationController class]]) {
activeController = [(UINavigationController*) activeController visibleViewController];
}
[activeController presentModalViewController:loginViewController animated:YES];
UIViewController *activeController = [UIApplication sharedApplication].keyWindow.rootViewController;
if ([activeController isKindOfClass:[UINavigationController class]])
{
activeController = [(UINavigationController*) activeController visibleViewController];
}
else if (activeController.modalViewController)
{
activeController = activeController.modalViewController;
}
[activeController presentModalViewController:vc animated:YES];
I ran into this problem on iOS 7 - the key to making any of the proposed solutions work was to call
[self.window makeKeyAndVisible];
in your AppDelegate.
After that call, presenting a modal view from the window's rootViewController worked.
Another reason for that warning can be that you want to present a view controller from an instance which is not the top most view controller.
So first you have to get the topmost UIViewController and using this instance to call presentViewController:
UIViewController *root = [UIApplication sharedApplication].keyWindow.rootViewController;
while (root.presentedViewController) {
root = root.presentedViewController;
}
You can NSLog(#"%#", self.window.rootViewController), and see what the rootViewController really is.
I came into this problem, when the rootViewController is a normal UIViewController.
Replace it with a UINavigationController, wish it will help.
Faced this issue while trying to present controller from the call of delegate of other controller . i.e : show search filter with delegate , once done back to my controller and receive data via the delegate then present controller , all I had to do is to dispatch the present code cause while in a delegate you're in another thread , that's why you're presenting on your view from main thread another controller from that other thread , so have to go back to main thread , just put the presenting code like this :
dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:searchVC animated:true completion:nil];
});
Hope this helps !

Dismiss ViewController + Table ViewController + Master-Detail app

I have a Master-Detail application. Both master and detail are UITableViewControllers. In detail scene I created a button and call to it action
- (IBAction)completeTaskButtonPressed:(id)sender {
[[self delegate] removeCompletedTask:self.indexFromRow controller:self];
}
In Master VC implementation I have method
- (void) removeCompletedTask:(NSInteger)index controller:(DetailViewController *) controller {
[self.dataController.masterTasksList removeObjectAtIndex:index];
[self.tableView reloadData];
[self dismissViewControllerAnimated:YES completion:NULL];
}
These method must delete selected row and go back to the Master View. The problem is that it removes the row but DONT dismiss detail view. Any help will be usefull.
Sounds like your master-detail setup involves a navigation controller. If you want to dismiss the detail view in the same manner as would tapping the Back button, use [self.navigationController popViewControllerAnimated:YES].
try
[self dismissModalViewControllerAnimated:YES];
or you could try:
[self.navigationController popViewControllerAnimated:YES].
You are popping the view controller which is the opposite of pushViewController: