IOS making buttons to work between viewcontrollers - ios

I asked a question similiar to this before and got many answers first of all thanks for them but because of the complexity of the project I didnt understand the answer so I decided to ask it again this time in a very simple form.
I have one button in viewcontrollerA and I want that button to write on a Label which is in viewcontrollerB.Its simple a button at A will set the Label text on B.
Example
User opens the app
Clicks the button at page A
Second Page comes up and in that page label text is set by the label.text code came from viewcontroller A it calls the code
Or maybe I can call the code of A from B its not important as long as I make it.I can make butons to open another viewcontrolers so you dont need to explain it.
Also if any other ways around and as long as they are simple I can do them too.Maybe I wrote the code elsewhere and call it from A and B.
Please explain it step by stem cause I have little knowlage about objective C and xcode.
I ask this question to learn about connections between viewcontrollers.In reality I will make that button to display a random number at the second page but its not important rightnow cause if I learn to make simple connection I can do the rest.

In your action, you need to have a reference to the second view controller. For example
- (IBAction)buttonAClicked:(id)sender {
ViewController2 *vc2 = [[ViewController2 alloc] initWithNibName:#"ViewController2" bundle:nil];
[self.navigationController pushViewController:vc2 animated:YES];
vc2.someVariable = #"This is random text";
[vc2.someButton setTitle:#"Some button text" forControlState:UIControlStateNormal];
}
This shows how you would create a second view controller, change two properties, and then push it.

In your second view controller create a property called theText that is an NSString and then in the viewDidLoad assign the label.text to the NSString;
- (void)viewDidLoad
{
if(self.theText)
self.label.text = self.theText;
}
Now use your first view controller to set theText in the second view controller.
If you are using a segue use prepareForSegue:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"Second View Segue"])
{
SecondViewController *theController = segue.destinationViewController;
theController.theText = #"Some text";
}
}
If you are using some sort of modal presentation:
SecondViewController *theController = [[SecondViewController alloc] init];
theController.theText = #"Some text";
[self presentModalViewController:theController animated:YES];
or if you are using a navigation controller:
SecondViewController *theController = [[SecondViewController alloc] init];
theController.theText = #"Some text";
[self.navigationController pushViewController:theController animated:YES];
So your first view controller will set the NSString property in the second, then the second will set the UILabel equal to the NSString during it's load. You can not set the text of a UILabel before the second view controller is loaded, so something like:
SecondViewController *theController = [[SecondViewController alloc] init];
theController.label.text = #"Some text";
[self.navigationController pushViewController:theController animated:YES];
will not work correctly, because you can't set the text for the label until the view is loaded.
Hope that helps.

Related

Button not responding to selector

UPDATED FOR COMMENTS
I am trying to make this code work, but whenever I press the "nextButton", the program ends and I cannot figure out what went wrong. Can you please look at my code and figure out if anything is wrong.
- (void)viewDidLoad {
[super viewDidLoad];
Player1.placeholder = #"Player 1";
Player2.placeholder = #"Player 2";
Notes1.placeholder = #"Notes";
Notes2.placeholder = #"Notes";
[nextButton setAction:#selector(nextButtonPressed:)];
}
-(IBAction)nextButtonPressed:(id)sender {
if ([self.delegateP respondsToSelector: #selector(addPlayerViewController:didFinishEnteringPlayer1:didFinishEneteringPlayer2:)]) {
[self.delegateP addPlayerViewController:self didFinishEnteringPlayer1:Player1.text didFinishEneteringPlayer2:Player2.text];
NSLog(#"Works");
}
[self performSelector:#selector(nextButtonPressed:) withObject:nil afterDelay:0.25];
}
I also have another question to do with this code. To pass information through different view controllers using delegates, do you have to use a button or a bar button item?
The error that is displaying:
-[UIStoryboardPushSegueTemplate nextButtonPressed:]: unrecognized selector sent to instance
First you can´t put both lines:
[self presentModalViewController:gameDetails animated:YES];
[self.navigationController pushViewController: gameDetails animated:YES];
Second go to your viewController PlayersViewController and click in storyboard click on editor (top menú XCode) Embed In > Navigation Controller now you with your code change the next lines:
-(void) nextButtonPressed {
NSLog(#"Hi my friend");
[self performSegueWithIdentifier:#"YOUR_SEGUE_NAME_HERE" sender:#"hi"];}
And create new function:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
{
// Get reference to the destination view controller
YourViewController *vc = [segue destinationViewController];
// Pass any objects to the view controller here, like...
[vc setMyObjectHere:sender];
}}
The ViewController "YourViewController.h :
#interface YourViewController : UIViewController
#property (nonatomic, strong) NSString *MyObjectHere;
#end
Try setting a symbolic breakpoint on all Objective-C exceptions and see if that gives you your crash line numbers and error messages again.
The code you posted for setting up the target/action on your bar button item looks correct.
Edit: Disregard this part about changing the selector.
(I'm leaving it for continuity, but ignore it.)
One thing you might try is changing the selector to
:#selector(nextButtonPressed:) (Colon added)
And then adding the button as a parameter to your action method:
-(IBAction) nextButtonPressed: (UIButton *) sender
Action methods should work with or without the sender parameter, but
it's worth trying.
(Also you should add the IBAction keyword for clarity even if you're not hooking up the action in IB.)
EDIT: rmaddy pointed out that your code is trying to both modally present and push the same view controller. Don't do that. Do one thing or the other.
You should use either
[self presentModalViewController:gameDetails animated:YES];
(To present it as a modal)
or
[self.navigationController pushViewController: gameDetails animated:YES];
(To push it onto the navigation stack.
But not both. Doing both is almost certainly the cause of your crash.

Change the view to a new view with SplitViewController

I have a very simple design with 3 views (.xib):
MeuPrimeiroViewController
MeuSegundoViewController
MeuTerceiroViewController
I am using the SplitViewController class to divide the screen into two parts, by default is configured on only appdelegate.m class to split views 'MeuPrimeiroViewController' along with 'MeuSegundoViewController'.
All Im trying to do is, when the user tap the button inside my 'MeuPrimeiroViewController', he start a method existing inside my 'MeuSegundoViewController' and he push the 'MeuTerceiroViewController', for this I'm doing:
MeuPrimeiroViewController.m
-(IBAction)mudar:(id)sender{
MeuSegundoViewController *VC2 = [[MeuSegundoViewController alloc] init];
[VC2 mudar];
}
MeuSegundoViewController.m
-(void)mudar{
NSLog(#"Change Screen");
MeuTerceiroViewController *VC3 = [[MeuTerceiroViewController alloc] init];
[self.navigationController pushViewController:VC3 animated:YES];
}
The method 'mudar' is calling but the screen don't change, how to solve this problem?
If you want to change the detail view you should make in MeuPrimeiroViewController:
[self.splitViewController showDetailViewController:VC3 animated:YES];
If you want to change the the "list" view you should make in the MeuPrimeiroViewController:
[self showViewController:VC2 animated:YES];
I'm not sure if it's VC2 or VC3 you want to show, but I hope this helps!

Delegation: delegated method doesn't see outlets

I have two views in the Tab Bar View. I want my second view to inform first view, when its Text Fields have changed value. I've done all the necessary coding for it, but there is one problem - first view doesn't see connected label outlets in the method declaration.
Code of the second view:
- (IBAction)textFieldHasChanged:(UITextField *)sender {
id<HPAAddCarOverallInfoTVCDelegate> strongDelegate = [[HPAAddCarMainViewController alloc] init];
if([strongDelegate respondsToSelector:#selector(addCarOverallInfoVC:textFieldValueChanged:)]) {
[strongDelegate addCarOverallInfoVC:self textFieldValueChanged:sender.text];
}
}
Code of the first view:
-(void)addCarOverallInfoVC:(HPAAddCarOverallInfoTableViewController *)viewController textFieldValueChanged:(NSString *)value
{
self.overallVCFieldCount.text = value;
NSLog(#"%#", value);
}
self.overallVCFieldCount.text = value; - value exist, but textField doesn't.
As I think, problem belongs at this line of code:
id<HPAAddCarOverallInfoTVCDelegate> strongDelegate = [[HPAAddCarMainViewController alloc] init];
I guess, that delegate isn't exact view with which I am working with. Bouth views are loaded at the same time via storyboard. If I am correct with my thought, can you tell me please, how can I give a pointer to exact first view which as second view are loaded when Tab Bar View controller goes on the screen?
You're creating a new view controller in textFieldHasChanged. If you have that view controller in IB, instantiate it like this:
UIStoryboard *st = [UIStoryboard storyboardWithName:[[NSBundle mainBundle].infoDictionary objectForKey:#"UIMainStoryboardFile"] bundle:[NSBundle mainBundle]];
id<HPAAddCarOverallInfoTVCDelegate> strongDelegate = st instantiateViewControllerWithIdentifier:#"identifier"];
Where identifier is the identifier you have given your view controller in your storyboard.

Change between two view controllers programmatically at the first launch

I have two view controllers. First is empty, second contains a text field. If this field is empty, I need to move to the second controller automatically.
I tried this:
NSUInteger VCcount = self.navigationController.viewControllers.count;
UIViewController *btVC = self.navigationController.viewControllers[VCcount-2];
if([self.btViewController.Text.text isEqualToString:#""])
{
[self.navigationController pushViewController:btVC animated:YES];
}
and this:
UIViewController* btVC = [storyboard instantiateViewControllerWithIdentifier:#"BTViewController"];
But at the first launch program knows only current controller and doesn't know about thesecond.
How can I get there?
See the example below:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.textField.text = #"some text";
if (self.textField.text.length == 0) {
UIViewController *secondVC = [self.storyboard instantiateViewControllerWithIdentifier:#"secondVC"];
[self.navigationController pushViewController:secondVC animated:NO];
}
}
If you comment out the assignment of "some text" to the textField, the secondVC will be instantiated and presented. I don't know what exactly you are trying to achieve with first two lines of your presented code.
If the secondVC already exist, you can just take a reference to it by knowing its index on the stack, or inspecting viewControllers array of your navigationController before you push it to the stack. If it does not exist, you just instantiate it from storyboard (with the correct identifier) and push it.

ipad app wierd behavior

My ipad project is master-detail view based. There is a button on detail view's toolbar, when user tap on the button, it popup a popover view to show four buttons (as menu). Three of buttons' actions are like the following (the three buttons show three different model form sheets):
- (void) showOnlineSgf
{
NSLog(#"showOnlineSgf");
TGOOnlineSgfViewController *dlg =
[[TGOOnlineSgfViewController alloc] initWithNibName:#"TGOOnlineSgfViewController"
bundle:nil];
UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:dlg];
[nav setModalPresentationStyle:UIModalPresentationFormSheet];
[self presentViewController:nav animated:YES completion:nil];
dlg = nil;
nav = nil;
}
The other button's action is to show a MFMailComposeViewController. Code is like the following:
- (void) emailCurrentGame
{
NSLog(#"email current game");
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[self presentModalViewController:picker animated:YES];
picker = nil;
}
The weird behavior is that when I tap the button what should execute showOnlineSgf(), but emailCurrentGame() is actually executed. When I set a breakpoint in showOnlineSgf(), it's hit, and step by step, each statement in showOnlineSgf() is executed. But the result on screen is a MFMainComposeViewController shows up.
I know this question is hard to answer. Any idea is appreciated.
Check your outlet connection of your UIButton that triggers showOnlineSgf. Most likely you copy pasted your UIButton in Interface Builder, which causes it to copy its assigned action as well. Then you've connected your other action, resulting in your UIButton having two actions.
To resolve the problem, simply disconnect your UIButton that triggers showOnlineSgf from the emailCurrentGame action.
Sounds like you copy pasted in the interface builder an already connected button. Check if the button has more than one action assigned.

Resources