I'm new using storyboards and I'm facing this situation: A uinavigationcontroller contains a view controller (root controller) which contains ten buttons linked each one of then through storyboard to the same view controller.
The behavior of the second view controller depends on the button tapped in the first view controller, but how can identify which button is tapped (like tag value) and pass this info to second view controller?
Thank you.
To add on Daniel's answer:
First, add a public property onto your secondVC that is accessible from your first VC:
#interface SecondViewController : UIViewController
#property (nonatomic) int buttonTagClicked;
#end
You need to set tags up on your UIButtons. This is either done in storyboard or programmatically in your code. I would create a generic IBAction that each button is linked to. You can extract the tag off the button through the sender parameter later.
- (IBAction)buttonClicked:(id)sender
{
[self performSegueWithIdentifier:#"pushSegue" sender:sender];
}
That is linked up to
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"pushSegue"]) {
SecondViewController *destinationVC = (SecondViewController *)[segue destinationViewController];
UIButton *selectedButton = (UIButton *)sender;
destinationVC.buttonTagClicked = selectedButton.tag;
}
}
You can set a segueIdentifier for each connection. Then in your ViewController you could trigger an action based on the identifier you set.
e.g.:
If you select your connection in storyboard you can name it:
And in your ViewController you can trigger an action based on the identifier like this:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"segue1"]) {
UIViewController *destinationVC = [segue destinationViewController];
destinationVC.property = ...;
}
}
Related
I'm using Objective-C. I set a segue from a table view cell to a new view controller, and I want to set the properties for the new view controller using this method:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString: #"detail"]){
if([segue.destinationViewController isKindOfClass:[detailViewController class]]){
detailViewController *detail = (detailViewController *)segue.destinationViewController;
detail.label.text = #"QQQQQ";
}
}
I've set the segue's identifier to #"detail" already, and also connected the label code with the view controller in storyboard. But when I run this in my simulator, the label would never change.
at the time when prepareForSegue is called the destinationviewcontroller's outlets are not set yet.
what you have to do is create a property in your detailViewController class like
#property (copy, nonatomic) NSString *detailText;
then in prepareForSegue:
detailViewController *detail = (detailViewController *)segue.destinationViewController;
detail.detailText = #"QQQQQ";
and in your detailViewControllers viewDidLoad:
self.label.text = self.detailText;
I have a textField in my ViewController1. I have a push segue to my ViewController2 which also has a textField. I need to set the textField.text in my ViewController2 to be equal to the text in the textField in my ViewController1. Here's the code I have:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqual:#"ViewController2"])
{
ViewController2 *VCT = [segue destinationViewController];
VCT.title = #"View Controller #2";
VCT.textField.text = self.textField.text;
}
}
The title setter works just fine. Why is the textField not working?
You cannot set the text of the UITextField (and any other components like UILabel and UITextView) in the prepare for segue, because all view components of the recently allocated controller are not initialized yet (at this time, they are all nil), they only will be when the viewController is presented (and it's view loaded).
You have to create a NSString property in the presented viewController, and then, somewhere inside your another view controller, like viewDidLoad, set the text of the textField as this property value.
Like this:
In the viewController that will present the another viewController:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"ViewController2"])
{
ViewController2 *vc2 = [segue destinationViewController];
vc2.myString = self.textField.text;
}
}
And inside the presented viewController:
- (void)viewDidLoad
{
[super viewDidLoad];
(...)
self.textField.text = self.myString;
}
Check and see if "VCT.textField" is not nil at that point. I suspect that you'll find it is nil.
You either need to expose it via "#property (strong) IBOutlet UITextField * textField" or you need to store the string somewhere else (e.g. a "NSString" property?) which then loads the text field when the view is fully loaded.
I want to simply set the title on my destination view controller so that it shows in its navigation controller's navigation bar in the prepareForSegue: method however setting its title or navigationItem like so:
[segue.destinationViewController setTitle:#"doesn't work"];
[segue.destinationViewController.navigationItem setTitle:#"this either"];
doesn't work possibly because the destination's view controller's view isn't loaded yet. Can I do this without creating a custom destination view controller?
Try accessing your ViewController that is embedded in the UINavigationController like this.
First you give your segue an identifier in the interface builder, then you access the segue in the prepareForSegue method and set the title by accessing the topViewController property of the navigation controller you segue to.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"yourSegueIdentifier"]) {
UINavigationController *navController =
(UINavigationController*)[segue destinationViewController];
YourViewController *destViewController =
(YourViewController* )[navController topViewController];
destViewController.navgationItem.title.text = #"Your new title";
}
}
This is for a segue into another UITableView
Set a public NSString property in the destination UITableViewController file.
#property (strong, nonatomic) NSString *navBarTitle;
Override the setter in the .m file just to be sure.
- (void) setNavBarTitle:(NSString *)navBarTitle
{
_navBarTitle = navBarTitle;
}
In the originating tableView's segue method, pass whatever string you need in the title.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString: #"userDetails"]) {
UsersActivitiesTableViewController *destinationController = segue.destinationViewController;
//Get the index path of the cell the user just clicked
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
//Grab the object from the array of users if the next view requires a specific title for a user name etc.
UserMO *thisUser = [self.users objectAtIndex:indexPath.row];
//Pass the string you want as the title to the public NSString property
destinationController.navBarTitle = thisUser.name;
}
}
And now for the important bit....
In the destination controller, get the top controller of the view and set the title property, after the view is loaded, and before it has been displayed:
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController topViewController].title = self.navBarTitle;
}
If you want a static title this can now (i.e., in Xcode 4.6.3) this can be done in Storyboard simply by setting the title in the nav bar on the relevant view controller.
If however you want the nav bar title to change according to what view is being segued to, e.g., a detail of a particular table row, as far as I know that needs to be set programmatically.
It took me FOREVER (newbie, sigh!) to figure out how to modify Julian Vogels' correct answer to call the key I wanted to use. Here's what worked:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"DetailSegue"]) {
// Fetch Item
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSDictionary *item = [self.groceries objectAtIndex:[indexPath row]];
// Configure Detail View Controller
TPDetailViewController *vc = [segue destinationViewController];
vc.navigationItem.title = [item objectForKey:#"name"];
[vc setItem:item];
}
If the segue is a push segue - which it should be if you're using a UINavigationController - then the destination view controller is automatically added to the window hierarchy, and you don't even need to identify the UINavigationController:
if ([segue.identifier isEqualToString:#"yourSegueNameHere"]) {
[segue.destinationViewController setTitle:#"yourTitleHere"];
}
I have a Navigation Controller and 2 Views Controllers. The first View Controller is associated with a UIViewController named ViewController. The second is connected to a UIViewController named BookVC. BookVC has a UITextField and is connected via an outlet:
#property (strong, nonatomic) IBOutlet UITextField *textFieldContent;
The connection is made with a button that uses a segue. I want to pass some data between the two and am using the following code which fails:
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
BookVC* nextPage = [[BookVC alloc] init];
nextPage = [segue destinationViewController];
nextPage.textFieldContent.text=#"Some content";
}
How should I pass data between the View Controllers?
I think the problem is that textFieldContent doesn't exist at that point. You'll need to add a property to BookVC that can hold the text you want to put into textFieldContent... we'll call it #property NSString *textFieldContentText. So then,
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
BookVC *nextPage = [segue destinationViewController];
[nextPage setTextFieldContentText:#"Some content"];
...
}
And then, in the -viewDidLoad method of BookVC:
- (void)viewDidLoad
{
[textFieldContent setText:[self textFieldContentText]];
}
You don't need this line:
BookVC* nextPage = [[BookVC alloc] init];
That creates a brand new BookVC which you then go and overwrite in the next line.
Since you are using [segue destinationViewController] you should be good to go. What's happening when you segue to nextPage?
I'm using storyboard in my ipad application and successfully able to do transitions, use segues etc.
Currently I am showing pop over view controller on click of a button. I want to detect when the pop over dismisses.
How can I do it?
Here is what I did:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"popover"])
{
UIStoryboardPopoverSegue *pop = (UIStoryboardPopoverSegue*)segue;
pop.popoverController.delegate = self;
}
}
UIPopoverController
Now with my revelation that you're talking about a UIPopoverController, here are the steps:
Setup the UIPopoverController with an appropriate delegate (I'm assuming the "sender" view controller)
Have your "sender" conform to the UIPopoverControllerDelegate
Implement the – popoverControllerDidDismissPopover: message and have any detection logic here
Implement - prepareForSegue:sender: and use the segue's destinationController to both get a reference and set the delegate, something like below:
((MyViewController*)segue.destinationController).delegate = self;
Modal View Controller
Add a delegate to the view controller that is being presented
Name your segue if you haven't already
Have your base view controller implement - prepareForSegue:sender: (refer to the UIViewController documentation)
Assign the sending view controller as the modal view controller's delegate in prepareForSegue:sender:
Call a desired method on the delegate immediately before or after you call dismissModalViewControllerAnimated:
That is how I would approach this. I would also recommend having a formal protocol to conform your sending view controller with.
Create a segue in view controller:
#property (strong, nonatomic) UIStoryboardPopoverSegue* popSegue;
In XIB, create an identifier called "popover" for the view.
In Interface, write the following code:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if( [[segue identifier] isEqualToString:#"popover"] )
{
//[[segue destinationViewController] setDelegate:self];
NSLog(#"%#",[[segue destinationViewController] viewControllers]);
self.popSegue = (UIStoryboardPopoverSegue*)segue;
.
.
.
}
Write the following code to dismiss the pop over by coding:
[self.popSegue.popoverController dismissPopoverAnimated:YES];
Since UIStoryboardPopoverSegueis deprecated in iOS 9, you can use a UIStoryboardPopoverPresentationSegue.
Then in prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)you can set the delegate like this:
Swift:
if let identifier = segue.identifier where identifier == "showPopover" {
let destVC = segue.destinationViewController as! UIViewController
destVC.popoverPresentationController?.delegate = self
}
An Objective-C code for the question is below.
if ([segue.identifier isEqualToString:#"home_login"])
{
UIViewController *dest = segue.destinationViewController;
dest.popoverPresentationController.delegate = self;
}
- (BOOL) popoverPresentationControllerShouldDismissPopover:(UIPopoverPresentationController *)popoverPresentationController
{
return NO;
}