In -prepareForSegue:sender:, how do I check if the sender was the view controller in which the -prepareForSegue:sender: is written?
In other words, how do I compare the sender argument to see what was passed when calling -performSegueWithIdentifier:sender:
I tried:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"identifier"])
if ([(MyViewControllerClass *)sender isEqual:self]) {
// stuff
} else {...}
}
}
Also tried == in place of isEqual:.
The else part is always executed.
you can try this
if([sender isKindOfClass:[MyViewControllerClass class]){
//do stuff
}
Update: First below code was crap ofcourse, here the version that does make sense:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self performSegueWithIdentifier:#"segueIdentifier" sender:self];
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if (segue.sourceViewController == sender) {
NSLog(#"i have been the sender");
}
}
Stupid last version as reference what you should not do - answer to fast:
I think you don`t want to check the sender. The sender could also be a Button activating the segue - i guess that you want to check against the sourceViewController.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if (segue.sourceViewController == self) {
NSLog(#"i have been the source");
}
}
This will check if the segue will transition from the current ViewController.
Related
I am fresh in iOS and objective-c. I am learning how to use segues, especially unwind segue.
while reading, I got a bit confused about the usage of 'shouldPerformSegueForIdentifier' and 'performSegueForIdentifier'.
I created an example contains two 'ViewControllers', 'ViewController.m' as shown in the code posted below 'VC_1' and 'ServiceViewController'
my questions are:
-when and how should I use 'performSegueForIdentifier'
-when and how should I use 'shouldIPerformSegueForIdentifier'?
VC_1:
#import "ViewController.h"
#import "ServiceViewController.h"
#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)btnStartService:(UIButton *)sender {
if (sender.tag == 1) {
NSLog(#"CLICKED");
[self performSegueWithIdentifier:#"seguePassInterval" sender:(id)
sender];
}
}
-(IBAction)btnExitApp:(UIButton *)sender {
NSLog(#"EXIT_CLICKED");
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"seguePassInterval"]) {
((ServiceViewController*)segue.destinationViewController).data = #"testData"; //passing data to destinationViewController of type "TestViewController"
NSLog(#"SEGUE");
}
}
#end
img
The prepareForSegue method is called right before the segue is executed, and allow to pass data between ViewController among other things, you can by example check if the identifier of your segue is "XxX" and pass some data or if is "YYY" call for a method
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"seguePassInterval"]) {
((TestViewController*)segue.destinationViewController).data = #"testData"; //passing data to destinationViewController of type "TestViewController"
NSLog(#"SEGUE");
}
}
method performSegueWithIdentifier is used to as his name says execute a segue using his identifier, you can perform a segue when you need it
and finally shouldPerformSegue is used to avoid perform a segue if your app is in some state, for example if you don't have the destinationViewController data yet you can return false until you get that
Hope this helps
I have a segue that is being called progmatically by performSegueWithIdentifier: but it will not trigger. However, when I create the segue with a button press the segue works without a problem. I have also tried changing the name of my segue in code, and it produces a no segue with identifier error.
Here is my code (Note: the segue is called in two different places to check if it would work somewhere else in the code.)
#import "SignUpViewController.h"
#import "ProgressHUD.h"
#interface SignUpViewController ()
#end
#implementation SignUpViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self performSegueWithIdentifier:#"profilePic" sender:self];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#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.
}
*/
- (IBAction)createAnAccount:(id)sender {
[ProgressHUD show:#"Please Wait"];
if ([self.passwrod.text isEqualToString:self.confirmPassword.text]){
// Register User
PFUser *user = [PFUser user];
user.username = self.username.text;
user.password = self.passwrod.text;
user.email = self.eMail.text;
// other fields can be set if you want to save more information
NSString *name = [self.firstName.text stringByAppendingString:#" "];
NSString *fullName = [name stringByAppendingString:self.lastName.text];
user[#"name"] = fullName;
user[#"posts"] = #0;
user[#"score"] = #5;
user[#"followers"] = #0;
user[#"following"] = #0;
[user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (!error) {
// Hooray! Let them use the app now.
[self performSegueWithIdentifier:#"profilePic" sender:self];
[ProgressHUD showSuccess:nil];
NSLog(#"Perform Segue");
} else {
NSString *errorString = [error userInfo][#"error"];
// Show the errorString somewhere and let the user try again.
[ProgressHUD showError:errorString];
}
}];
} else {
// Alert User
[ProgressHUD showError:#"Please check your passwords as they do not match."];
}
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"Preparing for segue");
NSLog(#"Segue: %#", segue.identifier);
}
#end
Update for clarification: The prepareForSegue method is being called and logging.
Thanks for your help!
You shouldn't call performSegueWithIdentifier in viewDidLoad. In fact, I'm pretty sure you'll see a warning or error in the console if you do. Move the call to viewDidAppear instead.
The solution that worked for me was to delete all the segues to the view controller in question and then re-added them. This porbably won't work for everyone, but it is worth a shot.
I have four buttons and one segue. When any of these buttons get touch up inside event, it will load respective images on the destination view controller. For that, I am recognizing buttons through their tag property [each button (0,1,2,3)]. Here is my code:
- (IBAction)Session1Btn:(id)sender {
[self performSegueWithIdentifier:#"isSection" sender:self];
}
- (IBAction)Session2Btn:(id)sender {
[self performSegueWithIdentifier:#"isSection" sender:self];
}
- (IBAction)Session3Btn:(id)sender {
[self performSegueWithIdentifier:#"isSection" sender:self];
}
- (IBAction)Session4Btn:(id)sender {
[self performSegueWithIdentifier:#"isSection" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
SectionViewController *sVC=[segue destinationViewController];
if([segue.identifier isEqualToString:#"isSection"])
{
// the following line gives an error!
NSInteger tagIndex = [(UIButton *)sender tag];
[sVC setSelectedButton:[NSNumber numberWithInteger:tagIndex]];
}
}
However I am getting the following error:
You must have written UIButton UITouchUpInside event like this:
- (IBAction)buttonPressed:(id)sender
{
[self performSegueWithIdentifier:#"isSection" sender:sender];
}
Same way for all your buttons.
Now add one variable UIButton *selectedButton in .h file. and update your button event methods like below:
- (IBAction)buttonPressed:(id)sender
{
selectedButton = (UIButton *)sender;
[self performSegueWithIdentifier:#"isSection" sender:sender];
}
And now you have selectedButton reference, which can be used in other methods. So that,
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(UIButton *)sender {
SectionViewController *sVC=[segue destinationViewController];
if([segue.identifier isEqualToString:#"isSection"])
{
[sVC setSelectedButton:[NSNumber numberWithInteger: selectedButton.tag]];
}
}
Swift
Create property for the selected button:
var selectedButton: Int = Int()
In each IBAction assign selectedButton to either 1 or 2 and add performSegue(withIdentifier: "yourSegueIdentifier", sender: self).
In prepare for segue add the following:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if buttonTapped == 1 {
// what ever happens when first button selected
} else if buttonTapped == 2 {
// what ever happens when second button selected
}
}
Sorry if the title isn't very clear, but hopefully I can elaborate here.
I have a ViewController MatchLineupViewController, which displays 22 buttons to represent rugby players on a team. When the user taps any of these buttons, a modal segue is called programmatically in the following method:
- (IBAction) showSquadSelector:(UIButton *)sender {
[self performSegueWithIdentifier:#"SeguePopupSquad" sender:sender];
}
The modal ViewController which is then displayed is called SquadSelectViewController. It passes back a selected player object to the MatchLineupViewController, which is acting as a delegate. This works perfectly.
However, I want to assign the profile_picture attribute of the returned object to the UIButton that sent the segue in the first place.
EDIT - The returned object is an NSDictionary as shown in the following code:
- (void) selectPlayer:(NSDictionary *)player forButton:(UIButton *)sender {
[sender.imageView setImage:[UIImage imageWithContentsOfFile:[player objectForKey:#"profile_picture"]]];
}
How would I go about doing this? If you require any further code to understand what I am asking, I can provide it.
Many thanks,
Chris
EDIT -
- (IBAction) showSquadSelector:(UIButton *)sender {
[self performSegueWithIdentifier:#"SeguePopupSquad" sender:sender];
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"SeguePopupSquad"]) {
SquadSelectViewController *ssvc = (SquadSelectViewController *) segue.destinationViewController;
ssvc.myDelegate = self;
ssvc.senderButton = sender;
}
}
- (void) selectPlayer:(NSDictionary *)player forButton:(UIButton *)sender {
[sender.imageView setImage:[UIImage imageWithContentsOfFile:[player objectForKey:#"profile_picture"]]];
NSLog(#"%#", [player description]);
NSLog(#"%#", [sender description]);
}
You can forward the sender of your showSquadSelector: method to the segue, like this:
[self performSegueWithIdentifier:#"SeguePopupSquad" sender:sender];
The sender of the segue would be the button that triggered the segue, so the code triggered from the segue would know what button has triggered it: your prepareForSegue: would have the correct UIButton. You can now add it to the returned dictionary at a predetermined key (say, #"senderButton") and examine it upon the return from the segue.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Passing variables between view controllers
Let's say I have 3 buttons in the same ViewController(FirstController) with tags from 1-3. All three buttons opened a new ViewController(SecondController). But how can I, in the SecondController, check what button was pressed to get here, or maybe what segue was used? So the SecondController can perform different depending on which button was pressed to open it. I was maybe thinking about a switch and case.
There are 2 possible ways of doing this.
One way is to assign a unique segue to each button. On the method prepareForSegue: you identify the button and give that information to the destinationViewController:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"Button1Segue"]) {
[segue.destinationViewController setButton:1];
}
if ([segue.identifier isEqualToString:#"Button2Segue"]) {
...
}
The other way would be to create a property where you store the last pressed button.
- (IBAction)buttonTap:(id)sender {
self.lastPressedButton = sender.tag;
}
and in prepareForSegue: you would do:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"SecondControllerSegue"]) {
[segue.destinationViewController setButton: self.lastPressedButton];
}
}
Hope it helps
if (button.tag == 0) {
NSLog(#"Button one.");
} else if (button.tag == 1) {
NSLog(#"Button two.");
}
You would put something like this in the method that occurs just before the action of your three buttons. That could be viewWillDisappear, prepareForSegue, etc.
Best of luck!