In my application, I have 4 UIViewcontrollers - A, B, C and D.
From my UIViewController A, UIVIewControllers B or C or D can be presented. Suppose, from A, i have presented B. Then, on B, there is are two UIButtons, clicking on which, i need to dismiss B and Present C or dismiss B and Present D. This is happening successfully, but first, after dismissing B, the screen of A comes, and then it goes to C or D.
Here's what i did:
On Button Press On B, the action is:
{
UINavigationController *controller = (UINavigationController *)self.parentViewController;
NSLog(#"%#",[controller parentViewController]);
UITabBarController *tabBarReference = (UITabBarController *)[controller parentViewController];
HomePageViewController *presController = (HomePageViewController *)tabBarReference.presentingViewController;
[presController dismissTabControllerWithHandlerWithSenderAtIndex:1];
}
In A, i have these methods:
-(void)dismissTabControllerWithHandlerWithSenderAtIndex:(NSInteger)index
{
if(index == 0)
{
[self dismissViewControllerAnimated:NO completion:^{
[self aboutButtonPressed:self];
}];
}
else
{
[self dismissViewControllerAnimated:NO completion:^{
[self settingsButtonPressed:self];
}];
}
}
Here's the method i am calling..
- (IBAction)settingsButtonPressed:(id)sender
{
[self.contactUsView setHidden:YES];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *deviceType = [prefs objectForKey:#"DeviceType"];
NSString *iOSType = [prefs objectForKey:#"iOSType"];
if([iOSType isEqualToString:#"iOS7"])
{
if([deviceType isEqualToString:#"iPad"])
{
SettingsViewController *settingsPage = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController_iPad" bundle:NULL];
settingsPage.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentViewController:settingsPage animated:YES completion:NULL];
}
else
{
SettingsViewController *settingsPage = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController" bundle:NULL];
settingsPage.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentViewController:settingsPage animated:YES completion:NULL];
}
}
else
{
if([deviceType isEqualToString:#"iPad"])
{
SettingsViewController *settingsPage = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController_iPad_iOS6" bundle:NULL];
settingsPage.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentViewController:settingsPage animated:YES completion:NULL];
}
else
{
SettingsViewController *settingsPage = [[SettingsViewController alloc] initWithNibName:#"SettingsViewController_iOS6" bundle:NULL];
settingsPage.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentViewController:settingsPage animated:YES completion:NULL];
}
}
}
Ok here goes:-
Suppose viewcontroller A is the base & it presents either view controllers B or C.
Implement delegate/notifications where the view controller B or C has to be dismissed.
After sending the delegate or posting the notification, dismiss the current view controller without animation, i.e animation:NO.
This notification that was posted needs to be heard in view controller A.
Here you present the next view controller.
EDIT:-
-(void)dismissTabControllerWithHandlerWithSenderAtIndex:(NSInteger)index
{
if(index == 0)
{
[self dismissViewControllerAnimated:NO completion:nil];
[self aboutButtonPressed:self];
}
else
{
[self dismissViewControllerAnimated:NO completion:nil];
[self settingsButtonPressed:self];
}
}
Related
Open the default contact form to add a number
Add a number and click on cancel to remove and open new modal for confirmation
Select discard changes modal close
Now when I open the contact book then first open the modal with the last number I added in the contact book form which added from my app
here is my code:
[self updateRecord:contact withData:contactData];
CNContactViewController *controller = [CNContactViewController viewControllerForNewContact:contact];
controller.delegate = self;
dispatch_async(dispatch_get_main_queue(), ^{
UINavigationController* navigation = [[UINavigationController alloc] initWithRootViewController:controller];
UIViewController *viewController = (UIViewController*)[[[[UIApplication sharedApplication] delegate] window] rootViewController];
while (viewController.presentedViewController)
{
viewController = viewController.presentedViewController;
}
[viewController presentViewController:navigation animated:YES completion:nil];
self->updateContactPromise = resolve;
Below is delegate method code:
[viewController dismissViewControllerAnimated:YES completion:nil];
if(updateContactPromise) {
if (contact) {
NSDictionary *contactDict = [self contactToDictionary:contact withThumbnails:true];
updateContactPromise(contactDict);
} else {
updateContactPromise(nil);
}
updateContactPromise = nil;
}
}
There are three controllers here, AViewController, BViewController, CViewController,
the first step: AViewController present to BViewController;
BViewController *BVC = [[BViewController alloc]init];
[self presentViewController:BVC animated:YES completion:nil];
The second step: BViewController push to CViewController;
CViewController *CVC = [[CViewController alloc]init];
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:CVC];
[self.navigationController pushViewController:nav animated:YES];
Now, if I want to go back from CViewController to AViewController, what code should I write?
Just use this code:
self.dismissViewControllerAnimated(true, completion: nil)
to dismiss C ViewController, because C ViewController is now on the Navigation Stack. A present a navigation controller that contain B ViewController. B ViewController push C ViewController, so C is still in Navigation Controller.
You can look at my project here:
https://github.com/khuong291/TestTransition
You should present BViewController like this:
BViewController *BVC = [[BViewController alloc]init];
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:BVC];
//Setting For Transparent
nav.providesPresentationContextTransitionStyle = YES;
nav.definesPresentationContext = YES;
nav.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:nav animated:YES completion:nil];
and in BViewController implement:
- (void)viewWillDisappear:(BOOL)animated {
[self.navigationController setNavigationBarHidden:YES];
}
- (void)viewWillDisappear:(BOOL)animated{
[self.navigationController setNavigationBarHidden:NO];
}
And you can push to CViewController:
CViewController *CVC = [[CViewController alloc]init];
[self.navigationController pushViewController:CVC animated:YES];
And when you want back to A. Simple call it in C:
[self dismissViewControllerAnimated:YES completion:nil];
Currently, I have set up a log-in view for users of my app. Below is the code that presents this log-in view to the user:
// Handle how we present the view
if (self.notificationToProcess != nil) {
[self.navigationController dismissViewControllerAnimated:YES completion:^{
SWNotificationsViewController *viewController = [[NotificationsViewController alloc] init];
viewController.initialDataID = self.notificationToProcess[#"Data"];
self.notificationToProcess = nil;
[self.navigationController pushViewController:viewController animated:YES];
}];
} else if (self.detailURL != nil) {
[self.navigationController dismissViewControllerAnimated:YES completion:^{
WebViewController *wvc = [[WebViewController alloc] init];
wvc.URL = self.detailURL;
wvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.navigationController presentViewController:wvc animated:YES completion:nil];
self.detailURL = nil;
}];
} else {
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
What I'm attempting to do now is display a web-view first if the user has just updated the app. Below is what this new code looks like:
// Handle how we present the view.
if (self.notificationToProcess != nil) {
[self.navigationController dismissViewControllerAnimated:YES completion:^{
SWNotificationsViewController *viewController = [[SWNotificationsViewController alloc] init];
viewController.initialDataID = self.notificationToProcess[#"Data"];
self.notificationToProcess = nil;
[self.navigationController pushViewController:viewController animated:YES];
}];
} else if (self.detailURL != nil) {
[self.navigationController dismissViewControllerAnimated:YES completion:^{
SWWebViewController *wvc = [[SWWebViewController alloc] init];
wvc.URL = self.detailURL;
wvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.navigationController presentViewController:wvc animated:YES completion:nil];
self.detailURL = nil;
}];
else if (![versionOfLastRun isEqual:currentVersion])
{
SWWebViewController *webViewController = [[SWWebViewController alloc] init];
NSString *url=#"http://someurl";
webViewController.URL = url;
webViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.navigationController presentViewController:webViewController animated:YES completion:nil];
[[NSUserDefaults standardUserDefaults] setObject:currentVersion forKey:#"VersionOfLastRun"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
else if (versionOfLastRun == nil){
// First start after installing the app
}
else {
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
However, when I run the app, the web view is not displayed, I get a warning of:
Warning: Attempt to present ViewController on NavigationController whose view is not in the window hierarchy!
Can anyone help me diagnose the problem? Thank you!
Seems like your viewController is not in Navigation controller hierarchy. This means that your controller is not connected with navigation controller stack which should handle presented controllers.
The other thing that should help is setting your root view controller as follows:
self.window.rootViewController = self.ViewController;
EDIT: since you mention that you don't use storyboards, setting rootViewController should do the trick.
Try to set the window's rootViewController to the navigation controller after you initialize the navigation controller:
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:mainController];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = navController;
This is how I'm doing it without storyboards.
The problem was that I didn't call self.navigationController dismissViewControllerAnimated:YES completion:^
After correcting this (see listing below), my WebView was shown as expected.
else if (![versionOfLastRun isEqual:currentVersion])
{
[self.navigationController dismissViewControllerAnimated:YES completion:^{
SWWebViewController *webViewController = [[SWWebViewController alloc] init];
NSLog(#"%#", self.window.rootViewController);
NSString *url=#"http://devstatwatch.drbsystems.com/releases_mobile.php";
webViewController.URL = url;
webViewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.navigationController presentViewController:webViewController animated:YES completion:nil];
[[NSUserDefaults standardUserDefaults] setObject:currentVersion forKey:#"VersionOfLastRun"];
[[NSUserDefaults standardUserDefaults] synchronize];
}];
}
I come across this issue while doing some testing. I have presented a Modal view, called ModalView1. In ModalView1, when a button is pressed, another Modal view, called ModalView2 would be presented using presentViewController. Then I tried dismissing ModalView2 using dismissViewControllerAnimated but it is not working.
Here is the code fragment in button action
- (void) buttonAction: (UIButton*) sender
{
ModalView *ModalView2 = [[ModalView alloc] init];
[self presentViewController:ModalView2 animated:YES completion:nil];
[self dismissViewControllerAnimated:YES completion:nil];
}
Any help would be much appreciated. Thank you.
It's not clear what you are trying to do. I give you two options:
Presenting ModalView2 and then dismissing ModalView2 (makes no sense to me, but that's what I can read in your question)
- (void) buttonAction: (UIButton*) sender {
ModalView* modalView2 = [[ModalView alloc] init];
[self presentViewController:modalView2 animated:YES completion:^{
[modalView2 dismissViewControllerAnimated:YES completion:nil];
}];
}
Presenting ModalView2 and dismissing ModalView1:
- (void) buttonAction: (UIButton*) sender {
ModalView* modalView2 = [[ModalView alloc] init];
UIViewController* presentingViewController = self.presentingViewController;
[self dismissViewControllerAnimated:YES completion:^{
[presentingViewController presentViewController:modalView2 animated:YES completion:nil];
}];
}
at time present and dismiss not call so give some time
try this it working me
- (void) buttonAction: (UIButton*) sender
{
[self performSelector:#selector(call) withObject:nil afterDelay:.4];
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)call
{
ModalView *ModalView2 = [[ModalView alloc] init];
[self presentViewController:ModalView2 animated:YES completion:nil];
}
I have implemented a delegate for the SKStoreProductViewController.
I add that view controller into the key window's view controller.
I have also implemented a dismiss view controller code in the delegate function.
The question seems to be answer in this question.
Modal App Store won't dismiss
Yet, this problem still persist in my situation.
Display function
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
NSString *appURL = [NSString stringWithFormat:#"itms-apps://itunes.apple.com/%#/app/id%#",
[[NSLocale preferredLanguages] objectAtIndex:0], applicationID];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:appURL]];
} else {
NSDictionary* dict = [NSDictionary dictionaryWithObject:applicationID forKey:SKStoreProductParameterITunesItemIdentifier];
SKStoreProductViewController *viewCont = [[SKStoreProductViewController alloc] init];
viewCont.delegate = self;
[viewCont loadProductWithParameters:dict completionBlock:^(BOOL result, NSError *error)
{
UIViewController* viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
if (viewController)
{ [viewController presentViewController:viewCont animated:YES completion:nil]; }
}];
}
Delegate Function
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController
{
if (viewController)
{ [viewController dismissViewControllerAnimated:YES completion:nil]; }
}
The problem is that you must implement
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController
{
if (viewController)
{ [self dismissViewControllerAnimated:YES completion:nil]; }
}
inside the delegate class. If you implement it inside the class whose delegate is presenting the SKStoreProductViewController, it will not work because SKStoreProductViewController will try to call productViewControllerDidFinish: within it's delegate, which isn't implementing that method.
Let me show an example:
#implementation MainViewController
- (void)presentSecondViewController
{
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[secondViewController setDelegate:self];
[self presentViewController:secondViewController animated:YES completion:nil];
}
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController
{
if (viewController)
{ [self dismissViewControllerAnimated:YES completion:nil]; }
}
#end
#implementation SecondViewController {
id delegate <SKStoreProductViewControllerDelegate>;
}
- (void)setDelegate:(id)delegate
{
_delegate = delegate;
}
- (void)callStoreProductViewController
{
SKStoreProductViewController *viewCont = [[SKStoreProductViewController alloc] init];
viewCont.delegate = _delegate;
[viewCont loadProductWithParameters:dict completionBlock:^(BOOL result, NSError *error)
{
UIViewController* viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
if (viewController)
{ [_delegate presentViewController:viewCont animated:YES completion:nil]; }
}];
}
#end
So, if I did understand your problem well, you must implement productViewControllerDidFinish: inside your viewController class, as it is the one who is presentig the SKStoreProductViewController.
Hope this helps!
Please try in Delegate function, replace all lines with:
[self dismissViewControllerAnimated:YES completion:nil];
Where does this code reside? You set the delegate to the instance where this code is written, but you are adding the SKStoreProductViewController to the root view.
Have you tried adding the store to self?
[self presentViewController:storeController animated:YES completion:nil];
Thanks for the delegate function. It isn't obvious in the documentation.