How to change to a view controller programmatically? - ios

I want to transition to a view I made in the main.storyboard, when they enter the password correctly.
How do I do this?
I need it to pull up the view I already created. I want a transition in the code block -(void) unlock.
Code
//
// ViewController.m
// Login
//
// Created by Ben Rosen on 5/24/14.
// Copyright (c) 2014 Ben Rosen. All rights reserved.
//
#import "ViewController.h"
#import "UnlockedScreen.h"
#interface ViewController ()
#end
#implementation ViewController
-(IBAction)login:(id)sender
{
NSString *correctUser = #"money";
NSString *correctPassword = #"ilovemoney";
if ((usernameTextField.text == correctUser)==YES && (passwordTextField.text = correctPassword)==YES)
{
[self unlock];
}
}
-(void) unlock
{
// here should be the transition
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent;
}
#end

In you storyboard, go on your first view controller, press CTRL click on the viewController and release the mouse (and CTRL) on the destination view controller.
Now choose type of segue (push if you are in a navigationController otherwise modal) and choose an identifier on the inspector for this trigger.
In your code:
-(IBAction)login:(id)sender
{
NSString *correctUser = #"money";
NSString *correctPassword = #"ilovemoney";
if ([usernameTextField.text isEqualToString:correctUser] && [passwordTextField.text isEqualToString:correctPassword])
{
[self performSegueWithIdentifier:#"name" sender:sender];
}
}
As you see i changed your if statement..your compare was wrong.

[self unlock];
remove it and write this method
[self performSegueWithIdentifier:#"profileSegue" sender:self] ;
in the storyboard name to identifier(profileSegue) on the inspector
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"profileSegue"]) {
ProfileViewController *profileViewController = segue.destinationViewController;
profileViewController.isFromDealView = YES;
profileViewController.hidesBottomBarWhenPushed = YES;
}

Instantiate your viewController with the identifier you have provided for your viewController.
-(void) unlock
{
// here should be the transition
UIViewController *vc = [[UIStoryboard storyboardWithName:#"storyboardname" bundle:nil] instantiateViewControllerWithIdentifier:#"viewControllersID"];
[self presentViewController:vc animated:YES completion:nil];
}

Related

prepareForSegue is not getting called

i created three scenes, each of them has a button and a label as shown in image-1. Scene1 is linked to Scene2 through "Show Segue called scene1To2"
,Scene2 is linked to scene3 through "Show Segue called scene2To3" and finally Scene3 is linked to scene1 through "Show Segue called scene3To1".
I am trying to to call "prepareForSegue" when the button in scene1 is clicked, so I wrote the code shown in code1 section below..
but when i run the code the NSLog message "NSLog(#"transiting from scene1To2");" does not show up
please let me know why the NSLog message doesn't show
code1:
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a
//nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)from1To2:(id)sender {
NSLog(#"Hi");
[self performSegueWithIdentifier:#"scene1To2" sender:self];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue
{
if ([segue.identifier isEqualToString:#"scene1To2"])
{
NSLog(#"transiting from scene1To2");
}
}
#end
Your method signature is wrong. See if this does the trick:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"scene1To2"])
{
NSLog(#"transiting from scene1To2");
}
}
In your Segue links on the storyboard have you added the segue name to the segue identifier?
You can use something like this, you import the scene1To2 controller.
scene1To2 *view = [[UIStoryboard storyboardWithName:#"YOUR_STORYBOARD" bundle:nil] instantiateViewControllerWithIdentifier:#"scene1To2"];
[self presentViewController:view animated:YES completion:nil];
then you go to the other view controller

Custom Delegate with Modal Form Sheet not working

I have gone through most of the previous related posts, but although I have followed them correctly (as far as i understood), I simply am not able to trigger the delegate method for below code.
Objective: ModalView generates a string *SQL_String. Press DONE to dismiss the ModalView and trigger the delegate method in the parentview to get that *SQL_String.
SearchModalViewController.h
#protocol SearchControllerDelegate
- (void)didDismissModalView:(NSString *)SQL_String;
#end
#interface SearchModalViewController : UIViewController
#property (nonatomic, assign) id <SearchControllerDelegate> searchDelegate;
- (IBAction)handleDone:(id)sender;
SearchModalViewController.m
#interface SearchModalViewController ()
#end
#implementation SearchModalViewController
#synthesize searchDelegate;
- (IBAction)handleDone:(id)sender {
[self dismissView:sender];
}
- (void)dismissView:(id)sender {
[searchDelegate didDismissModalView:#"Test"];
[self dismissViewControllerAnimated:YES completion:nil];
}
DetailViewController.m (My parent View Controller)
#interface DetailViewController () <SearchControllerDelegate>
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
SearchModalViewController *searchModal = [[SearchModalViewController alloc] init];
searchModal.searchDelegate = self;
}
PROBLEM:
Below delegate method is not getting triggered.
- (void)didDismissModalView:(NSString *)SQL_String {
[self dismissViewControllerAnimated:YES completion:nil];
NSLog(#"The string = %#", SQL_String);
}
Any idea where I am doing wrong?
EDIT: Thank you guys. With your fast suggestions, I am able to close it down by adding below code instead of my previous IB connection.
- (IBAction)showSearchModal:(id)sender {
SearchModalViewController *searchModal = [self.storyboard instantiateViewControllerWithIdentifier:#"search"];
searchModal.searchDelegate = self;
searchModal.modalPresentationStyle = UIModalPresentationFormSheet;
searchModal.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:searchModal animated:YES completion:nil];
}
Here it goes
Change DetailViewController.m
- (IBAction)pushToSearch:(id)sender{
SearchModalViewController *searchModal = [self.storyboard instantiateViewControllerWithIdentifier:#"search"];
searchModal.searchDelegate = self;
[self presentViewController:searchModal animated:YES completion:nil];
}
And it will work.
Firstly, make sure your dismissView: of the SearchModalViewController is getting triggered.
Secondly, make sure your searchDelegate in the dismissView: method is not nil.
You need to set the delegate when you present the SearchModalViewController. The reason why your code doesn't currently work, is because the modal view controller's delegate is nil.
Update:
You set the delegate in prepareForSegue:sender:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)__unused sender
{
if ([[segue identifier] isEqualToString:#"modalSearch"])
{
SearchModalViewController *controller = (SearchModalViewController *)[segue destinationViewController];
controller.delegate = self;
}
}

UINavigationController Broken in IOS 8?

I have a series of UIViewControllers in my app, and these are presented using a UINavigationController. The HOME ViewController calls pushViewController to get to the PROFILES ViewController. The PROFILES screen correctly shows the back button to HOME. Then selecting a button on PROFILES will take the user to the DETAIL ViewController. The DETAIL screen correctly shows the back button to PROFILES. But when I press the back button to PROFILES, I do indeed go back to the PROFILES screen but the navigation bar on that screen now shows the title HOME with no back button. In other words, it appears that IOS 8 has popped the ViewController once to go back from DETAIL to PROFILES, but has somehow popped the navigation bar items twice!
Any idea how I can fix this?
Apparently the solution outline can be found here:
UINavigationController and UINavigationBarDelegate.ShouldPopItem() with MonoTouch
In my solution, I just have all my view controllers extend CustomUINavigationController, which looks like this:
#import "CustomUINavigationController.h"
#import "IOSVersion.h"
#interface CustomUINavigationController ()
#end
#implementation CustomUINavigationController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.delegate=self;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//
// The following two methods are the key to overriding the buggy behavior in IOS 8
// The first method is from here:
// https://stackoverflow.com/questions/6413595/uinavigationcontroller-and-uinavigationbardelegate-shouldpopitem-with-monotouc
//
- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {
NSLog(#"Inside shouldPopItem");
if (regularPop) {
NSLog(#"regularPop is TRUE");
} else {
NSLog(#"regularPop is FALSE");
}
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0")) {
if (regularPop) {
regularPop = FALSE;
return YES;
}
regularPop = TRUE;
[self popViewControllerAnimated:YES];
return NO;
} else {
return [super navigationBar:navigationBar shouldPopItem:item];
}
}
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
{
NSLog(#"Inside popViewControllerAnimated");
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0")) {
NSMutableArray *viewControllers = [NSMutableArray arrayWithArray:self.viewControllers];
int cnt=(int)[viewControllers count];
NSLog(#"Inside popViewControllerAnimated, cnt is %d",cnt);
UIViewController *vc=[viewControllers objectAtIndex:cnt-2];
if (regularPop) self.desiredVC=vc;
[self popToViewController:vc animated:animated];
return vc;
} else {
return [super popViewControllerAnimated:animated];
}
}
- (UIViewController *)manualpopViewControllerAnimated:(BOOL)animated {
NSLog(#"Inside manualpopViewControllerAnimated");
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"8.0")) {
regularPop=TRUE;
return [self popViewControllerAnimated:animated];
} else {
return [super popViewControllerAnimated:animated];
}
}
- (void)navigationController:(UINavigationController *)navigationController
didShowViewController:(UIViewController *)viewController
animated:(BOOL)animated {
NSLog(#"Inside didShowViewController");
if (viewController==self.desiredVC) {
NSLog(#"Inside didShowViewController, found desiredVC");
regularPop = FALSE;
}
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end

IOS7 Change value of label in different view before segue (Same controller)

I have 2 simple views in my Storyboard and both use the same ViewController. I have the following code to switch the the second view...
self.labelStatus.text = #"CHECKING";
[self performSegueWithIdentifier:#"LoginSuccess" sender:sender];
*labelStatus is on the second view.
For some reason the labels text is not changing. Can anyone advise why this is?
[self performSegueWithIdentifier:#"LoginSuccess" sender:sender];
//change the label value in prepareForSegue: method
- (void)prepareForSegue:(UIStoryboardSegue *)segue {
if ([segue.identifier isEqualToString:#"LoginSuccess"]) {
UIViewController *loginVC = segue.destinationViewController;
//declare the string in .h file and assign it in viewDidLoad in loginVC
loginVC.labelString = #"CHECKING";
}
}
in loginViewController.h file
#property(nonatomic, strong) NSString *labelString;
in loginViewController.m file
- (void)viewDidLoad
{
[super viewDidLoad];
self.labelStatus.text = labelString
}
You can customise your destinationViewController (properties, views, etc) in prepareForSegue: method, which is called before segue is executed:
- (void)prepareForSegue:(UISegue *)segue {
if ([segue.identifier isEqualToString:#"mySegue"]) {
UIViewController *destVC = segue.destinationViewController;
// do your customisation
}
}
Edit-
If you need to change the label in the same view controller, then you should modify the label in the prepareForSegue method.

Modal view reappearing after dismissal

I am calling a login view modally in the view did load method in the root view controller, but when I dissmiss the modal view controller it just reappears! any suggestions?
hears the code:
** .h **
//
// FirstViewController.h
// Voyager
//
// Created by Peter Unger on 9/1/13.
// Copyright (c) 2013 Penumbra Software. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#interface FirstViewController : UIViewController
#end
#interface DefaultSettingsViewController :
UIViewController <PFLogInViewControllerDelegate, PFSignUpViewControllerDelegate>
#end
** .m **
//
// FirstViewController.m
// Voyager
//
// Created by Peter Unger on 9/1/13.
// Copyright (c) 2013 Penumbra Software. All rights reserved.
//
#import "FirstViewController.h"
#import <Parse/Parse.h>
#interface FirstViewController ()
#end
#implementation FirstViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
PFLogInViewController *login = [[PFLogInViewController alloc] init];
login.fields = PFLogInFieldsUsernameAndPassword | PFLogInFieldsLogInButton | PFLogInFieldsSignUpButton;
login.delegate = (id)self;
login.signUpController.delegate = (id)self;
[self presentViewController:login animated:YES completion:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)logInViewController:(PFLogInViewController *)logInController didLogInUser:(PFUser *)user {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)signUpViewController:(PFSignUpViewController *)signUpController didSignUpUser:(PFUser *)user {
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
As #Bergasms already said, you have a loop. the viewDidAppear method is called everytime your viewController appears in the screen. So, when you resign the presented viewController, the first view controller was supposed to appear, calling then the viewDidAppear, which will present again the PFLogInViewController, creating a loop.
If you move the code to the viewDidLoad method, your modal will be called just once, as this method is called only when the viewController is allocated.
And if you want the user to do not see the first viewController, you may want to set the animation in the presentViewController:animated:completion: to NO.
Edit:
One person said in another question that you might get an error if you call another view controller inside viewDidLoad (although I have done this once, haven't checked the behavior of the error yet). If that's your case and you get an error, you would have to let the code in viewDidAppear.
And if somehow you still want use viewDidAppear, you can simply create a BOOL property that controls if the PFLogInViewController was already called or not. It will be something like this
#property(nonatomic, assign) BOOL isLogged;
And
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if (!self.isLogged)
{
self.isLogged = YES;
PFLogInViewController *login = [[PFLogInViewController alloc] init];
login.fields = PFLogInFieldsUsernameAndPassword | PFLogInFieldsLogInButton | PFLogInFieldsSignUpButton;
login.delegate = (id)self;
login.signUpController.delegate = (id)self;
[self presentViewController:login animated:YES completion:nil];
}
}
In this way, your PFLogInViewController will be called once.
You have a loop there. When the modal controller is dismissed, the viewDidAppear method will be called on first view controller, which will launch the modal view again. You should put comments or break points at the launch code to help debug things like this.
#interface FirstViewController (){
BOOL has_shown_login_modal;
}
#end
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
has_shown_login_modal = NO;
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if(!has_shown_login_modal){
PFLogInViewController *login = [[PFLogInViewController alloc] init];
login.fields = PFLogInFieldsUsernameAndPassword | PFLogInFieldsLogInButton | PFLogInFieldsSignUpButton;
login.delegate = (id)self;
login.signUpController.delegate = (id)self;
[self presentViewController:login animated:YES completion:nil];
has_shown_login_modal = YES;
}
}

Resources