I am having a problems with the dismissViewControllerAnimated method not closing down the view.
What is happening in the app here is:
Cell in ItemViewController is selected.
View is pushed to ItemDetailViewControllerand details are sent through a delegate
User selects 'done' and the event is sent via a delegate to be closed in ItemViewController
All of this works except for the View is not dismissed, there are no errors. Can anyone see what is wrong?
- (void)itemDetailViewControllerDidFinish:(ItemDetailViewController *)controller
{
NSLog(#"Controller: %#", controller);
// Returns - Controller: <ItemDetailViewController: 0x6b68b60>
[self dismissViewControllerAnimated:YES completion:nil];
}
What if you call [controller.navigationController popViewControllerAnimated:YES] instead?
For that matter, what if you call [controller dismissViewControllerAnimated:YES completion:nil] instead of calling it on self?
The answer is in this page:
dismissviewcontrolleranimated-vs-popviewcontrolleranimated
dismissViewController is used when you do not have a navigationcontroller.
Most probably you are using a navigation controller, then use
self.navigationController popViewController instead.
Also take note of lemax his remark: use NULL, not nill for the completionhandler
I had a problem in iOS5 where the standard completion callback was not allowing the view to completely dismiss (only the current pushed view of that modal)
[controller dismissViewControllerAnimated:YES completion:^ {
//
}];
Solution for iOS5 is to not have a callback:
[controller dismissViewControllerAnimated:YES completion:nil];
Had a problem where calling dismissViewControllerAnimated dismissed the keyboard in a UIViewController, but not the view itself.
Solved it by using two calls:
[self dismissViewControllerAnimated:NO completion:nil];
[self dismissViewControllerAnimated:YES completion:nil];
an instant one for the keyboard, then an animated one for the controller
Your Situation is -
ItemViewController -> ItemDetailViewController
(pushed on navigationController)
Self.dismissViewController(..) dismiss a view controller that is presented over self(in ur case it is ItemViewController). Here, u did not presented any VC over self, instead u pushed a new VC over navigation stack. So, Correct way to dismiss ItemDetailViewController would be
self.navigationController.popViewController(true). please read the description of dismissViewController(....) to get more clarity.
Related
In my app I've 2 view controller that they appears by using a modal transition, now I developed the 3rd view controller and I put a button to go back to the main view controller, but how I can go back to the main view controller?
I tried with this:
[self dismissViewControllerAnimated:YES completion:nil];
but with this code I go back to the 2nd view controller. How I fix it?
Thank you!
Assuming your first modal presented the second modal, the following should work:
__weak UIViewController *vcThatPresentedCurrent = self.presentingViewController;
[self dismissViewControllerAnimated:YES completion:^{
[vcThatPresentedCurrent dismissViewControllerAnimated:YES completion:nil];
}];
Try with this....
[self.presentingViewController.presentingViewController
dismissViewControllerAnimated:YES completion:nil];
Let me know if you have any problem.
I am an iOS rookie. I have a Table View embedded in a Navigation Controller. Another Table View is also embedded in a Navigation Controller. The first Table View, ChecklistsView, presents the second Table View, ItemDetailView. The ChecklistView's Navigation Controller '+' button opens the ItemDetailView scene. Tapping on the Cancel button of the ItemDetailView closes the ItemDetailView, but gives the message noted above. Here is the code for the Cancel method:
- (IBAction)cancel
{
[self.delegate itemDetailViewControllerDidCancel:self];
}
And here is the delegate method used in the cancel method:
- (void)itemDetailViewControllerDidCancel:(ItemDetailViewController *)controller
{
[self dismissViewControllerAnimated:YES completion:nil];
}
Any suggestions would be appreciated. I have reviewed other posts about this warning, but they are above my level of expertise.
You shouldn't have the delegate dismiss the viewController.
Rather you should dismiss it by using the .presentingViewController property on the presentedViewController.
Like so:
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
I disagree with AdamG. What you're doing is correct; Apple also uses this design, where the delegate dismisses the controller (check out MFMessageComposeViewController).
Back to the question, if I understand you correctly, and that you have the following structure (pardon the terms, but you'll get the gist):
A UINavigationController at the top
ChecklistsViewController is the navigation controller's root view controller
ItemDetailViewController as a modal view controller
ChecklistsViewController is the delegate for ItemDetailViewController
It's just the implementation details in your case.
- (void) itemDetailViewControllerDidCancel: (ItemDetailViewController*) controller
{
[controller dismissViewControllerAnimated: YES
completion: nil];
}
I have TWO UIViewController classes, where in FirstClass i have an UIButton for Login, when user taps on button, i will display SecondClass... For that i have done,
SecondClass *index = [[SecondClass alloc] init];
[self presentModalViewController:index animated:YES];
In SecondClass i have a logout button, which will redirect to FirstClass, for that i have done,
[self dismissModalViewControllerAnimated:YES];
When i press Logout button in SecondClass, i get the warning msg
**Attempt to dismiss from view controller <FirstClass: 0e39w88e160> while a presentation or dismiss is in progress!**
What is the problem here..
Added both iOS 6 and pre-iOS 6 answers:
iOS 5.0 and later
When you logout, add this check before dismissing:
if (![self.presentedViewController isBeingDismissed])
{
[self dismissModalViewControllerAnimated:YES completion:nil];
}
iOS 4.X and less
Add this check before dismissing:
if (![[self modalViewController] isBeingDismissed])
{
[self dismissModalViewControllerAnimated:YES];
}
Call these lines where you logout & then check:
if (![[self modalViewController] isBeingDismissed])
{
[self dismissModalViewControllerAnimated:YES];
}
There are many things that may cause this, here are some options:
You forgot to call super on one of the ViewController methods such as viewWillAppear, viewWillAppear etc. Consult the UIViewController documentation to see when you have to call super.
The dismissModalViewControllerAnimated: method is being called more than once, this can happen if you added a target to the UIButton more than once.
To get better understanding of the problem please paste the code of both view controllers in its entirety.
The view controller may got by pushViewController or presentModalViewController from super view controller. In this view controller how should I know which way the controller from? I need it to close the view --
if (presentModalViewController ) {
[self dismissModalViewControllerAnimated:YES];
}else{
[self.navigationController popViewControllerAnimated:YES];
}
thanks
self.navigationController will be nil if the view is not in a nav controller (for example because it was presented). Of course if you present and have a nav controller, you'll need to dig deeper.
Additionally "self.presentingViewController" may be nil if you were not presented.
Note a common idiom for iOS is to create a simple protocol to handle closing the view. The view that pushes/presents is the delegate and gets their "viewWantsToClose" target called. If you create a new Utility project, you'll see what I'm talking about. This is how Apple flips the "info" view closed. You could potentially let your view accept a block for the "doCloseAction".
You are responsible for pushing or presenting a view so you should know when to pop or dismiss a view. If you still have to perform this kind of check, you can verify from the child view if self.navigationController is nil or not
You can do:
if (self.navigationController == nil) {
//[self dismissModalViewControllerAnimated:YES]; //Deprecated in iOS 6.0
[self dismissViewControllerAnimated:YES completion:nil];
}else{
[self.navigationController popViewControllerAnimated:YES];
}
or
NSArray* views = [self.navigationController viewControllers];
if (self.navigationController == nil || self == [views objectAtIndex:0])
{
//In the root view of navigationController or a presented View.
[self dismissViewControllerAnimated:YES completion:nil];
}else{
[self.navigationController popViewControllerAnimated:YES];
}
I'm having a problem getting my modal view controller to properly display and then dismiss. Basically I have a modally displayed login window and I want to dismiss it after all the data that I want to display is loaded from the database. if I call
[self dismissModalViewControllerAnimated:YES] from within the LoginViewController class it works perfectly fine but if I call
[[mainController modalViewController] dismissModalViewControllerAnimated:YES] from within my datamanager class after I have successfully imported the data nothing happens. Which is extremely confusing because [mainController modalViewController] points to the locationManager class.
Does anybody have any ideas as to why this isn't working? I'm programming for iOS 4 if that matters.
Thanks!
OK So I figured this out. Basically what was happening was that the [self dismissModalViewController] call was happening on another thread which for whatever reason means that the object did not properly process the dismiss message. I ended up using a notification and then called dismissModalView controller like so:
- (void)dismissSelf
{
[self dismissModalViewControllerAnimated:YES];
}
- (void)receiveDismissNotification:(NSNotification *) note
{
[self performSelectorOnMainThread:#selector(dismissSelf) withObject:nil waitUntilDone:NO];
}
which works
The proper way to dismiss a modal view controller is to call -dismissModalViewControllerAnimated: on the view controller that presented it. Thus it should be [_splitViewController dismissModalViewControllerAnimated:YES];.
From your comment, you need to call -dismissModalViewControllerAnimated: on the main thread, you can do this like so:
dispatch_async(dispatch_get_main_queue(), ^{
[_splitViewController dismissModalViewControllerAnimated:YES];
});
To close the Model View Controller use following code
[self dismissModalViewControllerAnimated:YES];
This code works with ios 5 also.
For presenting the model view controller
if (self.viewController!=nil)
{
//sanity check for view controller
[self.viewController SOMEVIEW animated:YES];
}