I have a splitviewcontroller that would call a loginview controller if there's a need for a login. This is how I would call the modal view
if([[NSUserDefaults standardUserDefaults] objectForKey:#"username"] == nil){
[self performSegueWithIdentifier:#"LoginSegue" sender:self];
}
This is how my storyboard looks like:
--- uinavigation
- masterview |
uispliviewcontroller
- detailview |
--- main dashboard view -(LoginSegue)--loginviewcontroller
|
|------ another viewcontroller
now I can get to the loginview without a problem and then I would try to dismiss the modal so it can go back to the maindashboard view using this
if([[NSUserDefaults standardUserDefaults] objectForKey:#"username"] != nil){
[self dismissViewControllerAnimated:YES completion:nil];
}
but it wouldn't do anything.
Was wondering how I can properly dismiss that modal view that was called after login?
Any advice is very much appreciated.
Thanks!!!
For a login, a modal presentation might make more sense. Rather than connecting it with a segue, give the LoginViewController a Storyboard ID, like "LoginViewController". (delete the segue to it, select the login vc in storyboard and find the storyboard id field in the identity inspector).
Then, instead of performSegue, do this ...
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"LoginViewController"];
[self presentViewController:vc animated:YES completion:^{}];
Having done this, the dismiss will function as you expect it to.
Related
My app has a login view, a loading view,a split view, and a menu view.
On launch, the initial view is the login view. It proceeds to the loading view when the user logs in successfully. Once the data is loaded, I present the split view. On the split view, I have a menu that I present modally. Among the options for the menu is logout. When the user logs out, I want to return to the login view. So far, so good.
The problem is that when I check the view hierarchy, the split view is still beneath the login view. Theoretically, the user could create a situation with an infinite number of layered views in this way.
How can I get the user back to the login view and dismiss the split view?
I am using storyboards and segues to get to the split view. The login view pushes to the loading view which pushes to the split view. I present the modal menu in a custom modal presentation controller.
//VC1
-(IBAction)button_click:(id)sender
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ViewController2 *viewController2 = [storyboard instantiateViewControllerWithIdentifier:#"VC2"];
[self.navigationController pushViewController:viewController2 animated:YES];
}
//VC2
-(IBAction)button_click:(id)sender
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ViewController3 *viewController3 = [storyboard instantiateViewControllerWithIdentifier:#"VC3"];
[self.navigationController pushViewController:viewController3 animated:YES];
}
//VC3
// In .h file
#interface ViewController3 : UIViewController<ViewController4Delegate>
-(IBAction)button_click:(id)sender;
#end
//In .m file
-(IBAction)button_click:(id)sender
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ViewController4 *viewController4 = [storyboard instantiateViewControllerWithIdentifier:#"VC4"];
viewController4.delegate=self;
[self.navigationController presentViewController:viewController4 animated:YES completion:nil];
}
-(void)completed
{
[self.navigationController popToRootViewControllerAnimated:YES];
[self.parentViewController.parentViewController dismissViewControllerAnimated:YES completion:nil];
}
//VC4
//In .h file
#protocol ViewController4Delegate
-(void)completed;
#end
#interface ViewController4 : UIViewController
-(IBAction)button_click:(id)sender;
#property(nonatomic,weak) id <ViewController4Delegate> delegate
//In.m file
-(IBAction)button_click:(id)sender
{
[self dismissViewControllerAnimated:NO completion:^{
if(delegate)
{
[delegate completed];
}
}];
}
Do you have a navigation controller for this ViewController Hierarchy? Assuming you do have a navigation controller:
If the LoginView is set as the rootViewController for the Navigation Controller and the LoadingView and SplitView are "pushed" onto the Navigation Stack, then what you can do is you can dismiss the modal and in the completion block, you can pop to the root view controller -> which would be your Login Controller.
So in your LogoutModal you would do this on the Logout Button Click Handler:
[self.presentingViewController dismissViewControllerAnimated:YES completion:^{
[self.presentingViewController.navigationController popToRootViewControllerAnimated:YES];
}];
This dismisses the modal and then as soon as that is complete, it pops the navigation stack all the way back to the root view controller.
I have my presentViewController code set up like this:
ProductViewController *vc = [[ProductViewController alloc] init];
[self presentViewController:vc animated:YES completion:nil];
It indeed presents the vc controller, but I'm unable to tap anything on it, it's like a frozen screen. Is it because there is still a view on top of it? Or I shouldn't be using alloc] init?
ProductViewController is an existing view controller (it's actually the root view controller), so basically I'd just like the presentViewController to just go back to the root view controller.
Edit:
I have a ShippingViewController where the user enters name/shipping details.
Then they tap on "Checkout" button that presents the PaymentViewController (which has a navigation bar, all other View Controllers don't).
On the PaymentViewController, the user enters their credit card details and tap the "Pay" button.
If the payment is successful, I wish for ProductViewController (the initial/root view controller) to be presented. Currently if I am just calling dismissViewController, it presents ShippingViewController.
This seemed to take care of my problem:
NSString *storyboardName = #"Main";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"id"];
[self presentViewController:vc animated:YES completion:nil];
I have 3 different viewControllers. first one is the main page where you will see many thumbnail of images. Second controller will only open when an image is clicked. Last ViewController is the login which opens when the user is not logged in but trying to view the second controller or clicked login from the main controller. In the login controller I have a back button to go to main page. Remember the user can access login from two different ways. by clicking on the image or clicking login in the main controller directly. So the issue is the back button does work properly. When the login page is accessed from the main controller directly, then the back button works fine it takes you to the main page. However, if you click on any of the thumbnails the second controller will try to open but since your not logged in the login page will show and when you click the back button to send you to the main controller, it won't go to main instead it will reload the same page and you kind of stock in a loop you have to login or exit the app. any ideas why?
The First ViewController Identifier is set to "mainImages".
- (IBAction)backToMain:(id)sender {
[self dismissViewControllerAnimated:NO completion:nil];
NSString * storyboardName = #"MainStoryboard";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
UIViewController * MI = [storyboard instantiateViewControllerWithIdentifier:#"mainImages"];
UINavigationController *navController = self.navigationController;
if (navController) {
[navController pushViewController:MI animated:NO];
}
}
I also tried this but no luck:
[self dismissViewControllerAnimated:NO completion:nil];
UIViewController * MI = [self.storyboard instantiateViewControllerWithIdentifier:#"mainImages"];
[self presentViewController:MI animated:NO completion:nil];
Try this if you are presenting as modal:
- (IBAction)backToMain:(id)sender {
[self dismissViewControllerAnimated:NO completion:^{
UIWindow *window = [[UIApplication sharedApplication].windows firstObject];
UINavigationController *nav = (UINavigationController *)window.rootViewController;
[nav popToRootViewControllerAnimated:YES];
}];
}
If you need to "go back" from the login view to any other view (in this case 2 of them), you should try using a Modal Segue, a modal segue lose the navigation controller view stack but allow you to dismiss the login view and go back to you last view.
On the first (or thumbnail images view controller) show your new modal view as this:
UIViewController *modalViewController = [[UIViewController alloc] init];
[self presentViewController:modalViewController animated:YES completion:nil];
And then, to dismiss (on login view controller):
- (IBAction)backToMain:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
as you see on the image, on the normal case I click the button1 to call the second view and then I click the button2 to call the last view, and in a particular scenario I want to click the button1 to call the last view.
I added this on the methode viewDidLoad:
if(condition)
[self performSegueWithIdentifier:#"thirdview" sender:self];
but it is not working, any help please.
thank you.
You need to add a segue from ViewController1 to Viewcontroller3.
But if you do this with many viewControllers then it becomes messy, I call it the spaguetti segues.
The alternative is to present that viewController modally.
Example:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
ViewController3 *viewController =
[storyboard instantiateViewControllerWithIdentifier:#"viewController"];
[self presentViewController:viewController animated:YES completion:nil];
(make sure you give ViewController3 a storyboardId)
I have a view controller that has a button on it. The button is the Privacy Policy. When it's clicked it goes to the proper IBAction and I create the privacy controller.
- IBAction ...
{
PrivacyPolicyViewController *privacy = [[PrivacyPolicyViewController alloc] init];
.....
}
I want to create a modal view of the privacy controller that has a UIWebView that animates itself upward and a back button to close it in ios 7. The ways I see online all are ios 6 and seem deprecated.
Use something like this:
// assuming your controller has identifier "privacy" in the Storyboard
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
PrivacyPolicyViewController *privacy = (PrivacyPolicyViewController*)[storyboard instantiateViewControllerWithIdentifier:#"privacy"];
// present
[self presentViewController:privacy animated:YES completion:nil];
// dismiss
[self dismissViewControllerAnimated:YES completion:nil];
[self presentmodalviewcontroller:vc]; has been deprecated.
you can try for
[self presentViewController:viewController animated:YES completion:nil];
it will work for you..
If you are using Storyboards, you can use a segue to present a modal view controller as well, and do it programmatically.
In your storyboard, ctrl+drag from the File's owner icon in the bar under the starting view to the view you want to present modally, let go and select "modal".
click on the segue icon, and then in the Attributes inspector, give it an identifier, like "toNewView".
in your starting view controller's .m file, use this code to perform the modal segue: [self performSegueWithIdentifier:#"toNewView" sender:self];
It's a nice clean way to do it because you don't have to import a .h file to instantiate the second controller object for the presentViewController method.
To dismiss it, you just use an unwind segue.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
taskQueeDetails *privacy = (taskQueeDetails*)[storyboard instantiateViewControllerWithIdentifier:#"taskQueeDetails"];
// Present the modal
[self presentViewController:privacy animated:YES completion:nil];
use the code and change the string instantiateViewControllerWithIdentifier:#"taskQueeDetails"];
it will work fine