Two "performSegue" in same class to different Viewcontrollers - swift

I am trying to go to two different VC with two different buttons. With the 'newGeneratedListBtn i only want to go to vc1. With the 'newEmptyList' button i want to go to vc3 with a bool value which works. But when i click first button 'newGeneratedListBtn' to go to vc1 I get error: "Could not cast value of type 'AppName.vc1' to 'AppName.vc3'.
Seems like when i click button to vc1 it tries to send the same values as i want to send to vc3. How can i solve this?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
let value = true
//Button to VC1
#IBAction func newGeneratedListBtn(_ sender: UIButton) {
performSegue(withIdentifier: "unwindSegueToVC1", sender: self)
}
//Value to send to VC2
override func prepare (for segue: UIStoryboardSegue, sender: Any!) {
let vc = segue.destination as! ListView
vc.newEmptyListValue = value
}
//Button to VC2
#IBAction func newEmptyList(_ sender: UIButton) {
performSegue(withIdentifier: "valueSender2", sender: self)
}
}

You need to cast for a specific identifier
override func prepare (for segue: UIStoryboardSegue, sender: Any!) {
super.prepare(for:segue,sender:sender)
if segue.identifier == "valueSender2" {
let vc = segue.destination as! ListView
vc.newEmptyListValue = value
}
else {
// it's unwindSegueToVC1
}
}
as both
performSegue(withIdentifier: "unwindSegueToVC1", sender: self)
performSegue(withIdentifier: "valueSender2", sender: self)
with call prepare

The problem is there is only one implementation of prepare(for:sender:), like this:
override func prepare (for segue: UIStoryboardSegue, sender: Any!) {
let vc = segue.destination as! ListView
vc.newEmptyListValue = value
}
Both of your segues pass through that one method. You must use a switch or other condition to figure out which segue this is, and send the info appropriate to that segue.

Related

Changing a UILabel's text attribute according to where the segue was preformed

My issue here is that I would like to change a UILabel's text according to which button triggered the segue. My identifier of my QuestionViewController (second view controller) is "goToQuestion", I have 2 buttons a truth and a dare button, they're both UI Buttons that can perform segues to the QuestionViewController, now the main question is how can I update the my UILabel to say Truth if the segue was performed through the truthPressed UIButton and to say dare if segue was performed through darePressed, I'm sure it requires and if and else statement that has to be in the QuestionViewController, or an " if segue.identifier = darePressed ... " I'm just confused and would like someone to enlighten me
#IBAction func truthPressed(_ sender: UIButton) {
performSegue(withIdentifier: "goToQuestion", sender: self)
}
#IBAction func darePressed(_ sender: UIButton) {
performSegue(withIdentifier: "goToQuestion", sender: self)
}
You need to override prepare(for segue:
#IBAction func truthPressed(_ sender: UIButton) {
performSegue(withIdentifier: "goToQuestion", sender: "truth")
}
#IBAction func darePressed(_ sender: UIButton) {
performSegue(withIdentifier: "goToQuestion", sender: "dare")
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let des = segue.destination as? QuestionViewController {
des.sentValue = sender as! String
}
}
With
class QuestionViewController:UIViewController {
var sentValue = ""
override func viewDidLoad() {
super.viewDidLoad()
print(sentValue)
}
}

How to use tableView.row with NSStoryboardSegue

I'm trying to send details from selected cell in a NSTableView to another ViewController.
I have a button:
#IBAction func detailButtonTapped(_ sender: Any) {
performSegue(withIdentifier: "toDetailsVC", sender: self)
}
And a prepare for segue:
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
let row = self.tableView.row(for: sender as! NSButton)
if segue.identifier == "toDetailsVC" {
let destination = segue.destinationController as! DetailsVeiwController
destination.name = orders[row].name!
}
}
The error:
Could not cast value of type 'Test.ViewController' (0x100022b98) to 'NSButton' (0x7fff8b59b260).
When I check let row = self.tableView.row(for: sender as! NSButton) inside the button, it works fine.
Am I way off here? Where is this going wrong?
self is the view controller. You have to pass the sender which is the button. And I recommend to declare the sender parameter as the concrete type
#IBAction func detailButtonTapped(_ sender: NSButton) {
performSegue(withIdentifier: "toDetailsVC", sender: sender)
}

Passing variable in swift with segue

I'm using segue to open a new window in a xcode app.
The segue is correct, when I tap on the button the new window is shown.
I want to pass a string variable from FirstViewController to DetailViewController but I can't set the variable in the DetailViewController.
This is the code in FirstViewController:
if control == view.rightCalloutAccessoryView {
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let controller = segue.destination as! DetailViewController
controller.Name = "test"
}
performSegue(withIdentifier: "showdetail", sender: self)
}
And this the DetailViewController code
class DetailViewController: UIViewController, WKNavigationDelegate {
var Name: String = ""
override func viewDidLoad() {
super.viewDidLoad()
print(Name)
}
}
Where am I doing wrong?
The method prepare(for must be on the top level of the class.
And please name variables according to the guidelines with starting lowercase letter
func someMethod()
{
if control == view.rightCalloutAccessoryView {
performSegue(withIdentifier: "showdetail", sender: self)
}
}
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let controller = segue.destination as! DetailViewController
controller.name = "test"
}
}

Execute a function from other view controller

I have the following interfaces:
In the table view I set the new values for the user and I would like to call the function to update the data from the server when the button "Done" from the main view is pressed.
How I can do it?
I have tried:
#IBAction func doneTapped(_ sender: Any){
ProfileEditingTableViewController().updateData()
}
But all the text fields from the other view are null because it seems to be a new instance of ProfileEditingTableViewController.
updateData() can't be static.
class ProfileEditingViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func cancelButton(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
#IBAction func doneTapped(_ sender: Any) {
// Here I have to save the data from the other View
dismiss(animated: true, completion: nil)
}
}
class ProfileEditingTableViewController: UITableViewController {
func updateData() {
...
}
}
This line
ProfileEditingTableViewController().updateData()
is incorrect as it creates a new instance, you need to use delegate to access the presented ProfileEditingTableViewController
class ProfileEditingTableViewController: UITableViewController {
var profileInstance: ProfileEditingViewController!
}
When you present information from profile:
let info = //
info.delegate = self // here self is the profile instance
Then use:
profileInstance.updateData()
//
Edit: connect the segue source to the vc itself ( yellow circular icon ) , this inside ( ProfileEditingViewController)
self.performSegue(withIdentifier: "goToNext", sender: nil)
//
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if segue.identifier == "goToNext" {
let des = segue.destination as! ProfileEditingTableViewController
des.profileInstance = self
}
}

How to pass two textfield entries to another ViewController with using segue

I want my user to go to the TableViewController once they enter their "id" and "password" but when we use prepare and performsegue methods we just send one variable.
#IBAction func logIn(_ sender: Any) {
performSegue(withIdentifier: "emailSegue", sender: emailTextField.text)
performSegue(withIdentifier: "passwordSegue", sender: passwordTextField.text)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let guest = segue.destination as! ExpenseTableViewController
guest.incoming.append(sender as! String)
}
As you can see here I want to perform two different segues and I have also created two segues on the storyboard from ViewController to tableview controller named as "emailSegue" and "passwordSegue", but in the prepare function I can only prepare for the one of them which is the "emailSegue" when I run the code, it does compile and I can append email to the array but not my password.
So I wonder how I can get them both to be sent? Is there a way to prepare for 2 different segues? Could not find an example of it on anywhere else.
Thanks in advance.
You can only perform one segue, but you can send multiple parameters.
Just pass an array rather than a single string:
#IBAction func logIn(_ sender: Any) {
performSegue(withIdentifier: "emailSegue",
sender: [emailTextField.text!, passwordTextField.text!])
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "emailSegue" {
let guest = segue.destination as! ExpenseTableViewController
guest.incoming.append(contentsOf: sender as! [String])
}
}
PS: Rather than forced unwrapping the text properties you should validate them:
#IBAction func logIn(_ sender: Any) {
guard let email = emailTextField.text, !email.isEmpty,
let password = passwordTextField.text, !password.isEmpty else {
// show an alert
return
}
performSegue(withIdentifier: "emailSegue", sender: [email, password])
}
You can only perform one segue at a time, so call performSegue only once when you want the transition to happen and set the two variables in prepareForSegue for the destination view controller. It's best to check what type of segue should be prepared by checking segue.identifier property.