I have many annotations in a mapview (with rightCalloutAccessory buttons). The button will perform a segue from this mapview to a tableview. I want to pass the tableview a different object (that holds data) depending on which callout button was clicked.
For example: (totally made up)
annotation1 (Austin) -> pass data obj 1 (relevant to Austin)
annotation2 (Dallas) -> pass data obj 2 (relevant to Dallas)
annotation3 (Houston) -> pass data obj 3 and so on... (you get the
idea)
I am able to detect which callout button was clicked.
I'm using prepareForSegue: to pass the data obj to the destination ViewController. Since I cannot make this call take an extra argument for the data obj I require, what are some elegant ways to achieve the same effect (dynamic data obj)?
Any tip would be appreciated.
Simply grab a reference to the target view controller in prepareForSegue: method and pass any objects you need to there. Here's an example...
- (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:object];
}
}
REVISION: You can also use performSegueWithIdentifier:sender: method to activate the transition to a new view based on a selection or button press.
For instance, consider I had two view controllers. The first contains three buttons and the second needs to know which of those buttons has been pressed before the transition. You could wire the buttons up to an IBAction in your code which uses performSegueWithIdentifier: method, like this...
// When any of my buttons are pressed, push the next view
- (IBAction)buttonPressed:(id)sender
{
[self performSegueWithIdentifier:#"MySegue" sender:sender];
}
// This will get called too before the view appears
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"MySegue"]) {
// Get destination view
SecondView *vc = [segue destinationViewController];
// Get button tag number (or do whatever you need to do here, based on your object
NSInteger tagIndex = [(UIButton *)sender tag];
// Pass the information to your destination view
[vc setSelectedButton:tagIndex];
}
}
EDIT: The demo application I originally attached is now six years old, so I've removed it to avoid any confusion.
Sometimes it is helpful to avoid creating a compile-time dependency between two view controllers. Here's how you can do it without caring about the type of the destination view controller:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController respondsToSelector:#selector(setMyData:)]) {
[segue.destinationViewController performSelector:#selector(setMyData:)
withObject:myData];
}
}
So as long as your destination view controller declares a public property, e.g.:
#property (nonatomic, strong) MyData *myData;
you can set this property in the previous view controller as I described above.
In Swift 4.2 I would do something like that:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let yourVC = segue.destination as? YourViewController {
yourVC.yourData = self.someData
}
}
I have a sender class, like this
#class MyEntry;
#interface MySenderEntry : NSObject
#property (strong, nonatomic) MyEntry *entry;
#end
#implementation MySenderEntry
#end
I use this sender class for passing objects to prepareForSeque:sender:
-(void)didSelectItemAtIndexPath:(NSIndexPath*)indexPath
{
MySenderEntry *sender = [MySenderEntry new];
sender.entry = [_entries objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:SEGUE_IDENTIFIER_SHOW_ENTRY sender:sender];
}
-(void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_SHOW_ENTRY]) {
NSAssert([sender isKindOfClass:[MySenderEntry class]], #"MySenderEntry");
MySenderEntry *senderEntry = (MySenderEntry*)sender;
MyEntry *entry = senderEntry.entry;
NSParameterAssert(entry);
[segue destinationViewController].delegate = self;
[segue destinationViewController].entry = entry;
return;
}
if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_HISTORY]) {
// ...
return;
}
if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_FAVORITE]) {
// ...
return;
}
}
I came across this question when I was trying to learn how to pass data from one View Controller to another. I need something visual to help me learn though, so this answer is a supplement to the others already here. It is a little more general than the original question but it can be adapted to work.
This basic example works like this:
The idea is to pass a string from the text field in the First View Controller to the label in the Second View Controller.
First View Controller
import UIKit
class FirstViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
// This function is called before the segue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// get a reference to the second view controller
let secondViewController = segue.destinationViewController as! SecondViewController
// set a variable in the second view controller with the String to pass
secondViewController.receivedString = textField.text!
}
}
Second View Controller
import UIKit
class SecondViewController: UIViewController {
#IBOutlet weak var label: UILabel!
// This variable will hold the data being passed from the First View Controller
var receivedString = ""
override func viewDidLoad() {
super.viewDidLoad()
// Used the text from the First View Controller to set the label
label.text = receivedString
}
}
Remember to
Make the segue by control clicking on the button and draging it over to the Second View Controller.
Hook up the outlets for the UITextField and the UILabel.
Set the first and second View Controllers to the appropriate Swift files in IB.
Source
How to send data through segue (swift) (YouTube tutorial)
See also
View Controllers: Passing data forward and passing data back (fuller answer)
For Swift use this,
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var segueID = segue.identifier
if(segueID! == "yourSegueName"){
var yourVC:YourViewController = segue.destinationViewController as YourViewController
yourVC.objectOnYourVC = setObjectValueHere!
}
}
I've implemented a library with a category on UIViewController that simplifies this operation.
Basically, you set the parameters you want to pass over in a NSDictionary associated to the UI item that is performing the segue. It works with manual segues too.
For example, you can do
[self performSegueWithIdentifier:#"yourIdentifier" parameters:#{#"customParam1":customValue1, #"customValue2":customValue2}];
for a manual segue or create a button with a segue and use
[button setSegueParameters:#{#"customParam1":customValue1, #"customValue2":customValue2}];
If destination view controller is not key-value coding compliant for a key, nothing happens. It works with key-values too (useful for unwind segues).
Check it out here
https://github.com/stefanomondino/SMQuickSegue
My solution is similar.
// In destination class:
var AddressString:String = String()
// In segue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "seguetobiddetailpagefromleadbidder")
{
let secondViewController = segue.destinationViewController as! BidDetailPage
secondViewController.AddressString = pr.address as String
}
}
Just use this function.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let index = CategorytableView.indexPathForSelectedRow
let indexNumber = index?.row
let VC = segue.destination as! DestinationViewController
VC.value = self.data
}
I used this solution so that I could keep the invocation of the segue and the data communication within the same function:
private var segueCompletion : ((UIStoryboardSegue, Any?) -> Void)?
func performSegue(withIdentifier identifier: String, sender: Any?, completion: #escaping (UIStoryboardSegue, Any?) -> Void) {
self.segueCompletion = completion;
self.performSegue(withIdentifier: identifier, sender: sender);
self.segueCompletion = nil
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
self.segueCompletion?(segue, sender)
}
A use case would be something like:
func showData(id : Int){
someService.loadSomeData(id: id) {
data in
self.performSegue(withIdentifier: "showData", sender: self) {
storyboard, sender in
let dataView = storyboard.destination as! DataView
dataView.data = data
}
}
}
This seems to work for me, however, I'm not 100% sure that the perform and prepare functions are always executed on the same thread.
Related
I have many annotations in a mapview (with rightCalloutAccessory buttons). The button will perform a segue from this mapview to a tableview. I want to pass the tableview a different object (that holds data) depending on which callout button was clicked.
For example: (totally made up)
annotation1 (Austin) -> pass data obj 1 (relevant to Austin)
annotation2 (Dallas) -> pass data obj 2 (relevant to Dallas)
annotation3 (Houston) -> pass data obj 3 and so on... (you get the
idea)
I am able to detect which callout button was clicked.
I'm using prepareForSegue: to pass the data obj to the destination ViewController. Since I cannot make this call take an extra argument for the data obj I require, what are some elegant ways to achieve the same effect (dynamic data obj)?
Any tip would be appreciated.
Simply grab a reference to the target view controller in prepareForSegue: method and pass any objects you need to there. Here's an example...
- (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:object];
}
}
REVISION: You can also use performSegueWithIdentifier:sender: method to activate the transition to a new view based on a selection or button press.
For instance, consider I had two view controllers. The first contains three buttons and the second needs to know which of those buttons has been pressed before the transition. You could wire the buttons up to an IBAction in your code which uses performSegueWithIdentifier: method, like this...
// When any of my buttons are pressed, push the next view
- (IBAction)buttonPressed:(id)sender
{
[self performSegueWithIdentifier:#"MySegue" sender:sender];
}
// This will get called too before the view appears
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"MySegue"]) {
// Get destination view
SecondView *vc = [segue destinationViewController];
// Get button tag number (or do whatever you need to do here, based on your object
NSInteger tagIndex = [(UIButton *)sender tag];
// Pass the information to your destination view
[vc setSelectedButton:tagIndex];
}
}
EDIT: The demo application I originally attached is now six years old, so I've removed it to avoid any confusion.
Sometimes it is helpful to avoid creating a compile-time dependency between two view controllers. Here's how you can do it without caring about the type of the destination view controller:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.destinationViewController respondsToSelector:#selector(setMyData:)]) {
[segue.destinationViewController performSelector:#selector(setMyData:)
withObject:myData];
}
}
So as long as your destination view controller declares a public property, e.g.:
#property (nonatomic, strong) MyData *myData;
you can set this property in the previous view controller as I described above.
In Swift 4.2 I would do something like that:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let yourVC = segue.destination as? YourViewController {
yourVC.yourData = self.someData
}
}
I have a sender class, like this
#class MyEntry;
#interface MySenderEntry : NSObject
#property (strong, nonatomic) MyEntry *entry;
#end
#implementation MySenderEntry
#end
I use this sender class for passing objects to prepareForSeque:sender:
-(void)didSelectItemAtIndexPath:(NSIndexPath*)indexPath
{
MySenderEntry *sender = [MySenderEntry new];
sender.entry = [_entries objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:SEGUE_IDENTIFIER_SHOW_ENTRY sender:sender];
}
-(void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_SHOW_ENTRY]) {
NSAssert([sender isKindOfClass:[MySenderEntry class]], #"MySenderEntry");
MySenderEntry *senderEntry = (MySenderEntry*)sender;
MyEntry *entry = senderEntry.entry;
NSParameterAssert(entry);
[segue destinationViewController].delegate = self;
[segue destinationViewController].entry = entry;
return;
}
if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_HISTORY]) {
// ...
return;
}
if ([[segue identifier] isEqualToString:SEGUE_IDENTIFIER_FAVORITE]) {
// ...
return;
}
}
I came across this question when I was trying to learn how to pass data from one View Controller to another. I need something visual to help me learn though, so this answer is a supplement to the others already here. It is a little more general than the original question but it can be adapted to work.
This basic example works like this:
The idea is to pass a string from the text field in the First View Controller to the label in the Second View Controller.
First View Controller
import UIKit
class FirstViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
// This function is called before the segue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// get a reference to the second view controller
let secondViewController = segue.destinationViewController as! SecondViewController
// set a variable in the second view controller with the String to pass
secondViewController.receivedString = textField.text!
}
}
Second View Controller
import UIKit
class SecondViewController: UIViewController {
#IBOutlet weak var label: UILabel!
// This variable will hold the data being passed from the First View Controller
var receivedString = ""
override func viewDidLoad() {
super.viewDidLoad()
// Used the text from the First View Controller to set the label
label.text = receivedString
}
}
Remember to
Make the segue by control clicking on the button and draging it over to the Second View Controller.
Hook up the outlets for the UITextField and the UILabel.
Set the first and second View Controllers to the appropriate Swift files in IB.
Source
How to send data through segue (swift) (YouTube tutorial)
See also
View Controllers: Passing data forward and passing data back (fuller answer)
For Swift use this,
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var segueID = segue.identifier
if(segueID! == "yourSegueName"){
var yourVC:YourViewController = segue.destinationViewController as YourViewController
yourVC.objectOnYourVC = setObjectValueHere!
}
}
I've implemented a library with a category on UIViewController that simplifies this operation.
Basically, you set the parameters you want to pass over in a NSDictionary associated to the UI item that is performing the segue. It works with manual segues too.
For example, you can do
[self performSegueWithIdentifier:#"yourIdentifier" parameters:#{#"customParam1":customValue1, #"customValue2":customValue2}];
for a manual segue or create a button with a segue and use
[button setSegueParameters:#{#"customParam1":customValue1, #"customValue2":customValue2}];
If destination view controller is not key-value coding compliant for a key, nothing happens. It works with key-values too (useful for unwind segues).
Check it out here
https://github.com/stefanomondino/SMQuickSegue
My solution is similar.
// In destination class:
var AddressString:String = String()
// In segue:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "seguetobiddetailpagefromleadbidder")
{
let secondViewController = segue.destinationViewController as! BidDetailPage
secondViewController.AddressString = pr.address as String
}
}
Just use this function.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let index = CategorytableView.indexPathForSelectedRow
let indexNumber = index?.row
let VC = segue.destination as! DestinationViewController
VC.value = self.data
}
I used this solution so that I could keep the invocation of the segue and the data communication within the same function:
private var segueCompletion : ((UIStoryboardSegue, Any?) -> Void)?
func performSegue(withIdentifier identifier: String, sender: Any?, completion: #escaping (UIStoryboardSegue, Any?) -> Void) {
self.segueCompletion = completion;
self.performSegue(withIdentifier: identifier, sender: sender);
self.segueCompletion = nil
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
self.segueCompletion?(segue, sender)
}
A use case would be something like:
func showData(id : Int){
someService.loadSomeData(id: id) {
data in
self.performSegue(withIdentifier: "showData", sender: self) {
storyboard, sender in
let dataView = storyboard.destination as! DataView
dataView.data = data
}
}
}
This seems to work for me, however, I'm not 100% sure that the perform and prepare functions are always executed on the same thread.
I'm fairly new in using Swift Programming and need to pass some data to the Container view.
I have variables passed in to Eyewear Detail View Controller from another VC that I would like to then passed to the Container which is connected to a table.
In this, I have a dictionary of the information I like to put in the table.
I've been scratching my head to find an answer but to no luck on Google Search. Perhaps you guys can help me. Thanks!
You can use - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender to pass the data.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.destinationViewController isKindOfClass:[YourContainedViewController class]]) {
// set data here
}
}
Set segue identifier in storyboard, first of all. You could find the field where can set identifier after click segue link.
View Controller which will call next ViewController
func showSomeViewController() {
self.performSegueWithIdentifier("TestContainer", sender: self);
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "TestContainer")
{
let vc: TestViewController = segue.destinationViewController as! TestViewController
vc.tmpString = "say ho"
}
}
and TestViewController
class TestViewController: UIViewController {
var tmpString: String!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
Just wondering about the sender object.
I know that you can access it in the method prepareForSegue... but is it available at all in the next destinationViewController?
i.e. in the viewDidLoad could I access a segueSender object or something?
I haven't ever seen this in documentation I just thought it might be useful.
EDIT FOR CLARITY
I'm not asking how to perform a segue or find a segue or anything like this.
Say I have two view controllers (VCA and VCB).
There is a segue from VCA to VCB with the identifier "segue".
In VCA I run...
[self performSegueWithIdentifier:#"segue" sender:#"Hello world"];
My question is can I access the #"Hello world" string from VCB or is it only available in the prepareForSegue... method inside VCA?
i.e. can I access the segue sender object from the destination controller?
Yes you can.
Old question but Ill pop in an answer using swift
first you call
performSegueWithIdentifier("<#your segue identifier #>", sender: <#your object you wish to access in next viewController #>)
in prepareForSegue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let dest = segue.destinationViewController as! <# your destination vc #>
dest.<# sentThroughObject #> = sender
}
}
Then in vc you segue to have a var that will accept the passed through object
class NextViewController: UIViewController {
var <# sentThroughObject #> = AnyObject!()
//cast <# sentThroughObject #> as! <#your object#> to use
}
UPDATE: SWIFT 3
performSegue(withIdentifier: "<#your segue identifier #>", sender: <#Object you wish to send to next VC#>)
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
let destination = segue.destinationController as! <# cast to your destination VC #>
destination.sentViaSegueObject = sender as? <#your object#>
}
In destination VC have a property to accept the sent Object
var sentViaSegueObject = <#your object#>?
You can always get a segue from the storbyoard, and get the sourceViewController. Something like this:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"myStorboard" bundle:nil];
UIStoryboardSegue *mySegue = [storyboard instantiateViewControllerWithIdentifier:#"mySegue"];
[mySegue sourceViewController];
EDIT:
Comments beat me to it. ;)
If you are trying to pass an object from one view controller to the next you may want to do something like this:
In your parent view controller:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Only if you have multiple segues.
if ([segue.identifier isEqualToString:#"NameOfYourSegue"]) {
// Cast necessary to access properties of the destination view controller.
[(YourChildViewController *)segue.destinationViewController setObject:theObjectToPass];
}
}
You need to give your segue a name in the storyboard and declare a property for the object to pass in the destination view controller.
in iOS6 I noticed the new Container View but am not quite sure how to access it's controller from the containing view.
Scenario:
I want to access the labels in Alert view controller from the view controller that houses the container view.
There's a segue between them, can I use that?
Yes, you can use the segue to get access the child view controller (and its view and subviews). Give the segue an identifier (such as alertview_embed), using the Attributes inspector in Storyboard. Then have the parent view controller (the one housing the container view) implement a method like this:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSString * segueName = segue.identifier;
if ([segueName isEqualToString: #"alertview_embed"]) {
AlertViewController * childViewController = (AlertViewController *) [segue destinationViewController];
AlertView * alertView = childViewController.view;
// do something with the AlertView's subviews here...
}
}
You can do that simply with self.childViewControllers.lastObject (assuming you only have one child, otherwise use objectAtIndex:).
for Swift Programming
you can write like this
var containerViewController: ExampleViewController?
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// you can set this name in 'segue.embed' in storyboard
if segue.identifier == "checkinPopupIdentifierInStoryBoard" {
let connectContainerViewController = segue.destinationViewController as ExampleViewController
containerViewController = connectContainerViewController
}
}
The prepareForSegue approach works, but it relies on the segue identifier magic string. Maybe there's a better way.
If you know the class of the VC you're after, you can do this very neatly with a computed property:
var camperVan: CamperVanViewController? {
return childViewControllers.flatMap({ $0 as? CamperVanViewController }).first
// This works because `flatMap` removes nils
}
This relies on childViewControllers. While I agree it could be fragile to rely on the first one, naming the class you seek makes this seem quite solid.
An updated answer for Swift 3, using a computed property:
var jobSummaryViewController: JobSummaryViewController {
get {
let ctrl = childViewControllers.first(where: { $0 is JobSummaryViewController })
return ctrl as! JobSummaryViewController
}
}
This only iterates the list of children until it reaches the first match.
self.childViewControllers is more relevant when you need control from the parent. For instance, if the child controller is a table view and you want to reload it forcefully or change a property via a button tap or any other event on Parent View Controller, you can do it by accessing ChildViewController's instance and not via prepareForSegue. Both have their applications in different ways.
There is another way using Swift's switch statement on the type of the view controller :
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
switch segue.destination
{
case let aViewController as AViewController:
self.aViewController = aViewController
case let bViewController as BViewController:
self.bViewController = bViewController
default:
return
}
}
I use Code like:
- (IBAction)showCartItems:(id)sender{
ListOfCartItemsViewController *listOfItemsVC=[self.storyboard instantiateViewControllerWithIdentifier:#"ListOfCartItemsViewController"];
[self addChildViewController:listOfItemsVC];
}
In case someone is looking for Swift 3.0,
viewController1, viewController2 and so on will then be accessible.
let viewController1 : OneViewController!
let viewController2 : TwoViewController!
// Safety handling of optional String
if let identifier: String = segue.identifier {
switch identifier {
case "segueName1":
viewController1 = segue.destination as! OneViewController
break
case "segueName2":
viewController2 = segue.destination as! TwoViewController
break
// ... More cases can be inserted here ...
default:
// A new segue is added in the storyboard but not yet including in this switch
print("A case missing for segue identifier: \(identifier)")
break
}
} else {
// Either the segue or the identifier is inaccessible
print("WARNING: identifier in segue is not accessible")
}
With generic you can do some sweet things. Here is an extension to Array:
extension Array {
func firstMatchingType<Type>() -> Type? {
return first(where: { $0 is Type }) as? Type
}
}
You can then do this in your viewController:
var viewControllerInContainer: YourViewControllerClass? {
return childViewControllers.firstMatchingType()!
}
you can write like this
- (IBAction)showDetail:(UIButton *)sender {
DetailViewController *detailVc = [self.childViewControllers firstObject];
detailVc.lable.text = sender.titleLabel.text;
}
}
in my app I've a button that performs a segue programmatically:
- (void)myButtonMethod
{
//execute segue programmatically
[self performSegueWithIdentifier: #"MySegue" sender: self];
}
I would like to know if there is a way to reference the destination view and to pass it some parameters.
I know that in prepareForSegue method, I can refer to it with:myDestinationViewController *vc = [segue destinationViewController];, but I don't know how to this executing the segue programmatically.
Do you have any ideas?
Thanks, yassa
UPDATE:
I'm sorry for this question!!! I simply discovered that, even if the segue is invoked programmatically, the prepareForSegue method is called anyway and so it is possible to pass parameters in the same usual way.
The answer is simply that it makes no difference how the segue is triggered.
The prepareForSegue:sender: method is called in any case and this is where you pass your parameters across.
Old question but here's the code on how to do what you are asking. In this case I am passing data from a selected cell in a table view to another view controller.
in the .h file of the trget view:
#property(weak, nonatomic) NSObject* dataModel;
in the .m file:
#synthesize dataModel;
dataModel can be string, int, or like in this case it's a model that contains many items
- (void)someMethod {
[self performSegueWithIdentifier:#"loginMainSegue" sender:self];
}
OR...
- (void)someMethod {
UIViewController *myController = [self.storyboard instantiateViewControllerWithIdentifier:#"HomeController"];
[self.navigationController pushViewController: myController animated:YES];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"storyDetailsSegway"]) {
UITableViewCell *cell = (UITableViewCell *) sender;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
NSDictionary *storiesDict =[topStories objectAtIndex:[indexPath row]];
StoryModel *storyModel = [[StoryModel alloc] init];
storyModel = storiesDict;
StoryDetails *controller = (StoryDetails *)segue.destinationViewController;
controller.dataModel= storyModel;
}
}
Swift 4:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ExampleSegueIdentifier" {
if let destinationVC = segue.destination as? ExampleSegueVC {
destinationVC.exampleString = "Example"
}
}
}
Swift 3:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ExampleSegueIdentifier" {
if let destinationVC = segue.destinationViewController as? ExampleSegueVC {
destinationVC.exampleString = "Example"
}
}
}
I understand the problem of performing the segue at one place and maintaining the state to send parameters in prepare for segue.
I figured out a way to do this. I've added a property called userInfoDict to ViewControllers using a category. and I've override perform segue with identifier too, in such a way that If the sender is self(means the controller itself). It will pass this userInfoDict to the next ViewController.
Here instead of passing the whole UserInfoDict you can also pass the specific params, as sender and override accordingly.
1 thing you need to keep in mind. don't forget to call super method in ur performSegue method.
In case if you use new swift version.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ChannelMoreSegue" {
}
}