iphone - change view with button programmatically - iphone

I read this tutorial about storyboards on iphone dev. The guy changes views through a button. But the connection of the button is made through the interface builder. How can i do this programmatically, so i can make some checks (username/password for example) before the view is changed?
Thanks in advance.

Connect one view with other (not the button with the view).
Change the segue to custom and give it an identifier (in IB). Ex: Login
Then create an action and assign it to the button.
In the button action use:
[self performSegueWithIdentifier:#"Login" sender:self];
Create a Segue Class object and in the .m use something like:
UIViewController *dst = [self destinationViewController];
UIViewController *nav = [self sourceViewController];
//All your custom code
[nav presentModalViewController:dst animated:YES];
Edit: Forgot something important!
In IB, in the Segue configuratión, put in Segue Class, the name of the Segue Class created. Ex: LoginSegue is the name of the segue created, in Segue Class yo has to write "LoginSegue"
Edit: To Create the Class:
1.- Create a New File extending UIStoryBoardSegue, the .h gonna be something like:
#import <Foundation/Foundation.h>
#interface LoginSegue : UIStoryboardSegue
#end
2.- In the implementation, use the code above inside an method called perform:
-(void)perform
{
UIViewController *dst = [self destinationViewController];
UIViewController *nav = [self sourceViewController];
//Custom Code
[nav presentModalViewController:dst animated:YES];
}
If you need to access the property of the source viewController, you need to change:
UIViewController *nav = [self sourceViewController];
to
eYourClass *nav = [self sourceViewController];
Hope this help!

You can either create the button and drag the touchUpInside action to an IBAction in interface builder
or in code somewhere in viewDidLoad
[self.login addTarget:self action:#selector(loginTapped) forControlEvents:UIControlEventTouchUpInside];
Then the loginTapped method could look something like
- (void)loginTapped;
{
if ([self authenticateWithUsername:self.username.text password:self.password.text]) {
[self performSegueWithIdentifier:#"loginSuccessful" sender:self];
} else {
// Warn user about invalid username/password
}
}
This relies on you having created the segue in the storyboard with a name that matches the identifier argument

Related

from second ViewController to first ViewController

I have 2 ViewControllers, in 1st - TableView and in 2nd - button with label on it. When I click on the button in 2nd ViewController I need to go back on TableView and set in
cell.detailTextLabel.text
text from label on the button.
For go back to first view I use:
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
but how I can set label from second view to:
cell.detailTextLabel.text
in first view?????
I would define a protocol & delegate in the second view controller
#protocol SecondViewController;
#interface SecondViewController : UIViewController
#property (nonatomic, assign) id<SecondViewController> delegate;
#end
#protocol SecondViewController <NSObject>
- (void)secondViewController:(SecondViewController *)controller didTappedOnButton:(UIButton *)button;
#end
then when the button is tapped call the delegate:
- (IBAction)buttonTapped:(UIButton *)sender
{
// do somthing..
// then tell the delegate about the button tapped
[self.delegate secondViewController:self didTappedOnButton:sender];
}
In your first view controller implement the protocol
#interface FirstViewController : UIViewController <SecondViewControllerDelegate>
when you push the second view controller, set the first as the second delegate:
- (void)someMethodThatPushTheSecondViewController
{
SecondViewController *svc = [[SecondViewController alloc] init];
[self.navigationController pushViewController:svc animated:YES];
svc.delegate = self;
}
And implement the delegate method to get notified when the button tapped
- (void)secondViewController:(SecondViewController *)controller didTappedOnButton:(UIButton *)button
{
// do somthing after button tapped
// you can get the button title from button.titleLabel.text
}
To access a parent class method or property you gotta implement a protocol, and use it's delegates. You can access child class methods/properties using it's class object that you create in the current (parent) class. But how you want to access a parent class entity from a child class? YES, implementing protocols.
Or the newbie way: after tapping your button, save the needed value into NSUserDefaults. Then, when you go to your parent class (viewController 1), ion viewWillAppear, check that saved value, and if it's not nil, display it.
[self.navigationController popViewControllerAnimated:YES];

Passing UIViewController to another Button in another ViewController

I have three buttons like this each corresponds to a different UIViewController:
For example, I press button 1. It will pass to the start button the view controller corresponding to that number that it will show.
I need to be able to pass it in this button:
Is it possible?
Yes, just create the UIButton as property on the view controller shown on button tap. Then, in the handler for the button tap, use the button property on the new controller to assign the button before showing the new controller.
Sample code:
//here's your method invoked when pressing the button 1
- (IBAction) pressedButtonOne:(id) sender {
NewViewController *newVc = [[NewViewController alloc] initWithNibName:#"NewViewController" bundle:nil];
newVc.startButton = self.startButton;
}
Here's the code in the controller created when pressing button 1
NewViewController.h
#import <UIKit/UIKit.h>
#interface NewViewController : UIViewController
#property (nonatomic, retain) UIButton *startButton;
//NewViewController.m
- (void) viewDidLoad {
//use self.startButton here, for whatever you need
}
If I understand the question correctly: Let's talk for button one (you can generalize it to the other buttons and VC's). Say the associated viewController is called button1ViewController.
In your button1ViewController, declare a property called button (#property(strong,non atomic) UIButton *button - also synthesize)..
In your IBAction method.
-(IBAction) button1Tapped:(id)sender {
button1ViewController.button = sender;
[self presentViewController:button1ViewController;
}
Edit: I think I get the question now.
In your mainView controller declare an instance variable: UIViewController *pushedController.
Also declare instances Button1ViewController *button1ViewController;
, Button2ViewController *button2ViewController, Button3ViewController *button3ViewController.
Now:
-(IBAction) button1Pressed:(id)sender {
if (button1ViewController==nil) {
button1ViewController = [Button1ViewController alloc] init];
}
pushedController = button1ViewController;
}
-(IBAction) button2Pressed:(id)sender {
if (button2ViewController==nil) {
button2ViewController = [Button2ViewController alloc] init];
}
pushedController = button2ViewController;
}
//same thing for button 3 pressed with button 3 controller
-(IBAction) startButtonPressed:(id) sender {
if (pushedViewController!=nil)
[self presentViewController:pushedViewController animated:YES completion:NULL];
}
I think this should work, however I haven't tried the code myself.

Adding to table view using a modal view controller

everywhere on the internet I find examples of how to add rows into a table view by having a special row "Add Row" with a green plus. But I don't want that.
I want to have a plus button in the titlebar of MyTableViewController, and invoke some Modal Add View Controller with a XIB file with just a single text field to fill it in. In this Modal Add View Controller I want to fill in this text field, and after I press Done, Modal Add View Controller dismisses, and I want to find that text added to a MyTableViewController table view.
I have a property in my MyTableViewController to hold all the lines of it:
#property (nonatomic, retain) NSMutableArray *list;;
I just can't get adding rows to work. I don't see where I could do the
[list addObject:];
Here's the code of the MyTableViewController addItem method which I invoke, when a user presses a plus button in the titlebar:
- (IBAction) addItem: (id) sender;
{
NSLog(#"Adding item...");
//Preparing "Add View" which has a single text field
AddViewController *addViewController = [[AddViewController alloc] init];
addViewController.title = #"Add Item";
UINavigationController *modalController = [[UINavigationController alloc]
initWithRootViewController:addViewController];
[addViewController release];
// Showing the prepared Add View controller modally
[self.navigationController presentModalViewController:modalController animated:YES]
NSLog(#"Modal controller has been presented.");
[modalController release];
}
And here is the code in the AddViewController, which is invoked after the textfield is typed in and pressing Done in the titlebar:
- (IBAction) done: (id) sender
{
NSLog(#"Reached Done");
if (textField != nil) {
self.fieldText = textField.text;
}
NSLog(#"About to dissmiss modal controller...");
[[self parentViewController] dismissModalViewControllerAnimated:YES];
NSLog(#"Modal controller has been dismissed.");
}
It is pretty common to create a delegate protocol for such Add Controller and make the parent controller its delegate.
When the Add Controller is "done" (i.e. not cancelled with a possible Cancel button), it calls a delegate method, say, addControllerIsDone: to let the parent table view controller know that it should take the set value, add it to the list, and dismiss the Add controller.
You could also pass the list to the Add Controller and let it add the set value itself before the [parentViewController dismissModalViewControllerAnimated:YES] call.
It depends whether you want to keep the control of the list in your table view controller or you want to pass it to the Add Controller.
And after the Add Controller is dismissed, you can either figure out where the cell for new entry should be added in the tableView and insert it with a nice animation, reload the section (animation also possible) or whole tableView (animation not possible).
First option could looke like this:
#class AddViewController;
#protocol AddViewControllerDelegate <NSObject>
- (void)controllerIsDone:(AddViewController *)controller;
#end
#interface AddViewController : UIViewController
#property (nonatomic, assign) id<AddViewControllerDelegate> delegate;
#end
And the 'done' code
- (IBAction) done: (id) sender
{
......
[self.delegate controllerIsDone:self];
NSLog(#"About to dissmiss modal controller...");
[[self parentViewController] dismissModalViewControllerAnimated:YES];
NSLog(#"Modal controller has been dismissed.");
}
And the MyViewController:
#interface MyViewController : UIViewController <AddViewControllerDelegate>
#end
So it has to implement the controllerIsDone: method. Like this for example:
- (void)controllerIsDone:(AddViewController *)controller
{
[self.list addObject:controller.textField.text];
}
As the AddViewController dismisses itself, MyViewController doesn't have to do it in the delegate method. But the good practice would be that if you popped up the modal view controller, you should also dismiss it, just for symmetry's sake. ;)
In this case, of course the textField has to be a publicly accessible property.
I'm sure you'll figure out the second option.
Read up on Decorator pattern in Cocoa Fundamentals Guide.
After you dismiss your modal controller:
[self addObjectToMyModel:newObject];
such that if you called [tableView reloadData] it would show up, but you don't need to call that, instead:
you need to know where the new object will appear in your table, determine the indexPath, and:
NSIndexPath *indexPathOfInsertedCell = …;
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPathOfInsertCell]
withRowAnimation:UITableViewRowAnimationFade];

transfer information between navigation based application

I have application
I want a button to open another screen with done button
after click this button a data be transfered from the current screen to the previous one
like opening options screen , how to let the main view know the changes be done on this subview
Best regards
You can use properties for this.
Create a property in the second class: .h file
#interface DetailViewController : UIViewController {
NSString *head;
}
#property(nonatomic,retain)NSString *head;
#end
in .m file
#synthesize head;
Now in your firstviewcontroller or first class
if (dt==nil) {
DetailViewController *d = [[DetailViewController alloc]initWithNibName:#"Detailview" bundle:nil];
self.dt = d;
[d release];
}
dt.head=itemsum;
[self.navigationController pushViewController:self.dt animated:YES];
Suppose you have to pass NSString to other class then declare one Nsstring in second class and make accessor method for nsstring and then call this code from first view controller
yournextviewcontroller *viewcontroller = [[yournextviewcontroller alloc] initWithNibName:#"yournextviewcontroller" bundle:nil];
viewcontroller.Stringname = name;
[self.navigationController viewcontroller:evernotebook animated:YES];
You can take UIView as IBOutlet in the same ViewController. Show that view with click on Button like
IBOutlet UIView *yourAnotherScreenView; //Bind this to your view in XIB file.
[self.view addSubView:yourAnotherScreenView];
[self.view bringSubViewtoFront:yourAnotherScreenView];
Take Done button on the view and wireup the action event in the same controller and do the necessary stuff as required.
Use the simple delegate concept of Objective-C .
Check very simple answers in the below post for using delegate in Objective-C .
How do I set up a simple delegate to communicate between two view controllers?

How to switch to next view when button is pressed iPhone?

here is a iPhone programming beginner's question:
How do I get to another view by pressing a button in my main view?
I have the following function which is executed when I press a button, and debugging it, he passes there, but my "Warning" view does not show up:
-(IBAction) showWarningView:(id)sender
{
if(self.showWarning == nil){
WarningViewController *nextView = [[WarningViewController alloc] initWithNibName:#"Warning" bundle:[NSBundle mainBundle]];
self.showWarning = nextView;
[nextView release];
}
[self.navigationController pushViewController:self.showWarning animated:YES];
}
My main RootViewController looks like this:
#import <UIKit/UIKit.h>
#import "WarningViewController.h"
#interface RootViewController : UIViewController {
IBOutlet UIButton *button1;
WarningViewController *showWarning;
}
#property(nonatomic,retain) WarningViewController *showWarning;
-(IBAction) showWarningView:(id)sender;
#end
I am using the navigation control of a UITableViewController but what do I have to use to just simply show my other view when I press a button in a view-based application?
Thanks a lot!
edited
if you're using the navigation control of a UITableViewController, you probably have to push the view in you tableviewcontrollers navigation controller
this means you have pass the navigation controller of your tableviewcontroller on to your viewcontroller, then you just push it
e.g.
[self.tableViewControllersNavigationController pushViewController:self.showWarning animated:YES];
(for passing the tableViewController's navigationController on, you might have to create a delegate pattern)
Does the title in your navigation bar change? Maybe you don't have a UIView associated with your UIViewController inside your Interface Builder file.