I have a view controller called vc0 which is presented like this:
[self presentViewController: vc1 animated: YES completion: nil];
And in vc1 I have a button to present another view controller:
[self presentViewController: vc2 animated: YES completion: nil];
Then in vc2, I have a button to dismiss the view controller:
[self dismissViewControllerAnimated:YES completion: ^{
// over here I call one method in vc1
}
And as expected it returns back to vc1.. however there is a button in vc1 to go back to vc0 by dismissing the view controller like this:
[self dismissViewControllerAnimated:YES completion:nil];
But for some reason it doesn't work, the view controller does not get dismissed back to vc0. When I first present vc1, I can press the button to dismiss the view controller and it works. But when I press the button to open vc2, and when I dismiss vc2 back to vc1, and THEN I press the button to dismiss the view controller, that is when it doesn't work.
Sorry if the question is a bit unclear, it is a bit hard to phrase what I am trying to say.
Also one more thing:
I tried replacing dismissViewControllerAnimated:
in vc1 to manually present vc0, but then I get a log in the console saying that I am trying to present a vc0 but vc1's view is not in the window hierarchy. What does this mean?
Thanks for help!
UPDATE:
IN THIS CASE VC0 IS MenuMileIndexViewController
- VC1 IS FlightViewController
- VC2 IS BookmarksTableViewController
Here is code involved:
MenuMileIndexViewController:
- (IBAction)goToOriginPage {
FlightRecorder *origin = [[FlightRecorder alloc] init];
[self presentViewController:origin animated:YES completion:nil];
}
Flight Recorder:
- (void)searchBarBookmarkButtonClicked:(UISearchBar *)searchBar {
[self bringUpBookmarkkTable];
}
- (void) bringUpBookmarkkTable {
BookmarkTableViewController *bookmarkTVC = [[BookmarkTableViewController alloc] init];
[bookmarkTVC setModalTransitionStyle: UIModalTransitionStyleFlipHorizontal];
[self presentViewController:bookmarkTVC animated:YES completion:nil];
}
- (IBAction)cancel {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)endBookmarkProcessWithBookmarkCollection: (NSDictionary *)dict {
presetBookmarkContext = [dict mutableCopy];
bookmarkMode = YES;
NSString *compiledText = nil;
NSNumber *number1 = [NSNumber numberWithInt: 1];
if ([dict objectForKey: @"bookmarkTag"] == number1) {
compiledText = [NSString stringWithFormat: @"%@ to %@", [dict objectForKey: @"origin"], [dict objectForKey: @"destination"]];
}
else {
compiledText = [NSString stringWithFormat: @"%@ to %@", [dict objectForKey: @"destination"], [dict objectForKey: @"origin"]];
}
compiledText = [compiledText stringByReplacingOccurrencesOfString:@"Origin: " withString:@""];
compiledText = [compiledText stringByReplacingOccurrencesOfString:@"Destination: " withString:@""];
flightContext = [NSDictionary dictionaryWithObjectsAndKeys: [dict objectForKey: @"miles"], @"miles", compiledText, @"location", [[NSUserDefaults standardUserDefaults] objectForKey: @"tempD"], @"date", nil];
NSString *string = [NSString stringWithFormat: @"\nMiles: %.2f\nFlight: %@\nDate: %@", [[dict objectForKey: @"miles"] floatValue], compiledText, [[NSUserDefaults standardUserDefaults] objectForKey:@"tempD"]];
UIAlertView *bvkBookmarkAlertView = [[UIAlertView alloc] initWithTitle:@"Confirmation" message:string delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Add", nil];
[bvkBookmarkAlertView show];
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
[self cancel]; // Even though cancel is an IBAction, IBAction is the same thing as void so it is callable
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
[TheMileIndexViewController addDesiredMilesToIndex: [[flightContext objectForKey: @"miles"] doubleValue]];
[TravelLogViewController addFlight: flightContext];
if (!bookmarkMode) {
if ([checkbox isSelected]) {
[BookmarkHandler uploadBookmark: bookmarkFlightContext];
}
}
}
if (buttonIndex == 0) {
if ([alertView.title isEqualToString: @"Confirmation"]) {
bookmarkMode = NO;
}
}
}
BookmarksTableViewController:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated: YES];
NSDictionary *dict = [[BookmarkHandler bookmarkCollection] objectAtIndex: indexPath.row];
fl = [[FlightRecorder alloc] init];
[self dismissViewControllerAnimated:YES completion:^{
[fl endBookmarkProcessWithBookmarkCollection: dict];
}];
}
NOW, I have created a screen recording of the app in simulator showing what is the problem. I can email that to you for reference. So I can email that to you.
I would recommend to always dismiss a VC from the VC that actually presented it - using a delegate. This is actually also the Apple recommended way - as was pointed out in a previous answer to my question regarding this issue.
So if you have VC0 presenting VC1, have the dismiss VC1 code in VC0 too, using delegate scheme.
I have learned that this is the savest way to handle presenting and dismissing - even though sometimes it works to dismiss VC1 within VC1 itself.
I have asked a very related question, you might be interested to check this too. It shows the code...
ps I also read that some dismiss only VC1 - which in turn will also dismiss VC2. However, if my previous suggestion works, I would not do this. Sometimes I get information during execution (no crash) that the VC does not exist anymore or anything related to that - so I assumed this is not the best solution. But if my prvious suggestion does not work, you may try the second one.
Though no guarantee that this will last the updates to new iOS, since this issue keeps hauting me for several iOS updates now :-), so I decided to go the standard recommended route.
EDIT: This is my modified code - it works without problems - however it is not clear what you intend to happen AFTER the user reponds to the Alert and whether the Alert should be on VC1 or VC0. Anyway using delegate and callbacks I do not see any issue. Please explain should I have missed your point...
FlightViewControllerProtocol.h
@protocol FlightViewControllerProtocol <NSObject>
-(void) dismissVCAndEndBookmark;
@end
FlightViewController.m
#import "FlightViewController.h"
#import "FlightViewControllerProtocol.h"
#import "BookmarksTableViewController.h"
@interface FlightViewController ()
@end
@implementation FlightViewController
@synthesize delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)searchBarBookmarkButtonClicked:(UISearchBar *)searchBar {
[self bringUpBookmarkkTable];
}
- (IBAction) bringUpBookmarkkTable {
BookmarksTableViewController *bookmarkTVC = [[BookmarksTableViewController alloc] init];
bookmarkTVC.delegate = self;
[bookmarkTVC setModalTransitionStyle: UIModalTransitionStyleFlipHorizontal];
[self presentViewController:bookmarkTVC animated:YES completion:nil];
}
- (IBAction)cancel {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)endBookmarkProcessWithBookmarkCollection: (NSDictionary *)dict {
// presetBookmarkContext = [dict mutableCopy];
// bookmarkMode = YES;
NSString *compiledText = nil;
NSNumber *number1 = [NSNumber numberWithInt: 1];
if ([dict objectForKey: @"bookmarkTag"] == number1) {
compiledText = @"Text1";
}
else {
compiledText = @"Text2";
}
// flightContext = [NSDictionary dictionaryWithObjectsAndKeys: [dict objectForKey: @"miles"], @"miles", compiledText, @"location", [[NSUserDefaults standardUserDefaults] objectForKey: @"tempD"], @"date", nil];
NSString *string = compiledText;
UIAlertView *bvkBookmarkAlertView = [[UIAlertView alloc] initWithTitle:@"Confirmation" message:string delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Add", nil];
[bvkBookmarkAlertView show];
}
- (void) dismissVCAndEndBookmark {
[self dismissViewControllerAnimated:YES completion:nil];
[self endBookmarkProcessWithBookmarkCollection: nil];
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
[self cancel]; // Even though cancel is an IBAction, IBAction is the same thing as void so it is callable
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 1) {
NSLog(@"alertView1");
}
if (buttonIndex == 0) {
NSLog(@"alertView2");
}
}
@end
BookmarksTableViewController.h
@interface BookmarksTableViewController : UIViewController
{
id delegate;
}
@property (nonatomic,strong) id delegate;
@end
BookmarksTableViewController.m
- (IBAction)goBack {
[self.delegate dismissVCAndEndBookmark];
}
Esp the callback in BookmarksTableViewController.m seems to be the main issue in your implementation if I understood your intentions correctly.
[self.navigationController popViewControllerAnimated:YES];
did the trick for me also. In my case, I had a (iPhone) viewController that was pushed on to the stack using a push segue. Since the viewController that was initiating the segue had a navigation bar, I had to send the parent controller's navigationController the popViewControllerAnimated message instead of calling it's own dismissViewControllerAnimated:completion message.
Ray
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With