Passing UIViewController to another Button in another ViewController - iphone

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.

Related

iphone - change view with button programmatically

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

Why is my delegation between two vc's not working?

I have two view controllers. My first is my menu which contains my highscore and a button which performs a modal segue to my second view controller which is my game. Whenever my player loses the game if he beat his highscore I want it to update on the menu.
Right now, when my player loses the game, I create a UIAlertView with 2 buttons, the first is main menu and the second is restart. Here is my simplified code with my attempting to update my high score via delegation.
#protocol highScoreProtocol <NSObject>
-(void)updateHighScore:(int) score;
#end
#interface ViewController : UIViewController <UIAlertViewDelegate> //i have this delegate implemented because i have a uiialertview
#property (nonatomic) int score;
#property (nonatomic, weak) id <highScoreProtocol> delegateHighScore;
#implementation ViewController
#synthesize score=_score;
#synthesize delegateHighScore=_delegateHighScore;
-(void)lostGame{
[self.delegateHighScore updateHighScore:self.score]; //this is where i try to call the method that should update my high score if necessary but this doesn't actually work
UIAlertView *losingScreen=[[UIAlertView alloc]initWithTitle:#"Game Over" message:[NSString stringWithFormat:#"Your Score Is %d", self.score] delegate:self cancelButtonTitle:#"Main Menu" otherButtonTitles:#"Restart", nil]; //once the user loses the game i have an alert view show giving the option to either restart the game or go to the main menu where the high score is
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex==0) {
//here i'm segueing back to my main menu because he would have pressed the 'main menu' button [self performSegueWithIdentifier:#"MainMenu" sender:self];
} else if (buttonIndex==1){
//here i just reset my attributes and reset my level because he would have pressed the 'restart button'
}
}
#end
#interface MenuVC : UIViewController <highScoreProtocol>
#property (weak, nonatomic) IBOutlet UILabel *labelHighScore; //the labelhighscore is the highscore number
#end
#implementation MenuVC
- (void)viewDidLoad
{
[super viewDidLoad];
ViewController *vc=[[ViewController alloc]init];
vc.delegateHighScore=self;//here is set the delegate as myself which i think i'm supposed to do for some reason
}
-(void)updateHighScore:(int)score{
if (score>[self.labelHighScore.text integerValue]) {
self.labelHighScore.text=[NSString stringWithFormat:#"%d", score];
}
NSLog(#"does this method even run");
// this is the method that updates the highscore which I want to run
// but it doesn't, notice I even made an 'nslog' to see if the method
// even runs but I never ever even got a log out in the debugger,
// so this method never runs.
}
If I just need a little help, or if I'm doing everything completely wrong and going about this task the wrong way, please say.
This doesn't work because this:
ViewController *vc=[[ViewController alloc]init];
vc.delegateHighScore=self;
Instantiates a NEW viewcontroller, that has completely nothing to do with the one you are interacting with.
I assume you are using storyboards so, create an identifier for your viewcontroller (on the interface builder -> select your viewcontroller -> identity inspector tab -> write a name where it says Storyboard ID)
And then add this instead of the previous code:
ViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"yourIdentifier"];
vc.delegateHighScore = self;
Edit:
Add this to your button action (but delete the segue from the interface builder AND delete this code from the viewDidLoad)
ViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"yourIdentifier"];
vc.delegateHighScore = self;
[self presentModalViewController:vc animated:YES];
Since you create a local variable, vc, in your viewDidLoad method, this is not the same one that you create in the button method where you create your modal segue. That's not the right place to set the delegate. Set yourself to the delegate in that button method using whatever reference you create (or have) to the instance of ViewController that you're segueing to. If you need more information or a code sample, post that button method, so I can see how you are segueing.
After Edit: Then you should implement prepareForSegue:sender: and do this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
[(ViewController *)[segue destinationViewController] setDelegate:self];
}

Xcode moving from view to view

I'm coding in Xcode, and i have a problem moving from view to view (xib to xib) My xib-files all have a personal .h and .m file.
this is the code i have:
The code to go from the first view to the quiz view in this case:
-(IBAction)switchviewMainToQuiz:(id)sender {
ViewControllerQuiz *quizView = [[ViewControllerQuiz alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:quizView animated:YES];
}
The code to go back from a view to my first view:
-(IBAction)switchviewQuizToMain:(id)sender {
[self dismissModalViewControllerAnimated:YES];
}
the problem is that the second code just goes back and that gives sometimes an error or a fail in the app. So when i go to other views and then want to go back it often gets stuck. So does someone have an other code to switch the views, or maybe an other solution? Thank You!
I wouldn't create new viewController in IBAction. For me i would do this in this way:
1 Create property with viewController:
#property(nonatomic, strong) UIViewController *quizView ;
2 Synthesize it:
#synthesize quizView = _quizView;
3 Create method:
- (UIViewController *) quizView {
if (_quizView == nil) {
_quizView = [[ViewControllerQuiz alloc] initWithNibName:nil bundle:nil];
}
return _quizView;
}
4 In your IBAction:
-(IBAction)switchviewMainToQuiz:(id)sender {
[self presentModalViewController:self.quizView animated:YES];
}

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];

How do I create a sizeable subView

I'm looking to create a sizeable subview that's draggable like this:
If there is an IBAction that takes you to the next View (SecondViewController) and when it does, there's another IBAction there and when you click on that one, it creates a SubView that's about half of the size of the current screen you're in (SecondViewController) that shows the third view controller that would be created? Also, how would you make that subView draggable? Thank you for helping.
Sorry, just to be clear, you want your second view controller to have a button that when tapped, adds your third view controller taking up half the screen at the bottom?
If this is the case then you can do this with the new view controller containers in iOS5.
Ok, so you have three view controllers. For the sake of this lets say your class are called FirstViewController, SecondViewController and ThirdViewController.
I assume from what you say that you already have you instance of FirstViewController with a button, that moves you on to an instance of SecondViewController, and that the issue is then getting SecondViewController to add an instance of ThirdViewController to the bottom half of the screen when a button is pressed.
The .m file for SecondViewController will need to do something like this:
#import "ThirdViewController.h"
#interface SecondViewController ()
#property (retain) ThirdViewController *thirdViewConroller;
- (void)buttonTap;
#end
#implementation SecondViewController
#synthesize thirdViewConroller = _thirdViewConroller;
- (void)dealloc {
self.thirdViewConroller = nil;
[super dealloc];
}
- (void)loadView {
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.titleLabel.text = #"Show third controller";
[button addTarget:self action:#selector(buttonTap) forControlEvents:UIControlEventTouchUpInside];
button.frame = // Some CGRect of where you want the button to be
[self.view addSubview:button];
}
- (void)buttonTap {
// When the button is tapped, create an instance of your ThirdViewController and add it
self.thirdViewConroller = [[ThirdViewController alloc] initWithFrame:/* Some CGRect where you want the controller to be */ ];
[self.thirdViewConroller willMoveToParentViewController:self];
[self addChildViewController:self.thirdViewConroller];
[self.thirdViewConroller didMoveToParentViewController:self];
}
#end
This should give you a button on your second controller, that will create and add you third controller. Make sure yo us till have all the standard methods that you had before, this should be in addition to what you have.
In your interface for ThirdViewController:
#interface ThirdViewController : UIViewController <NSObject>
- (id)initWithFrame:(CGRect)frame;
#end
Then in the implementation of your ThirdViewController:
- (id)initWithFrame:(CGRect)frame {
self = [super initWithNibName:nil bundle:nil];
if (self) {
self.view.frame = frame;
// Do your init stuff here
}
return self;
}
It should then handle adding the views and such forth.
Make sure your thirdViewController class has a valid initWithFrame: initialiser method.
This should do the trick, if you need any further help let me know :)