How to use tableView.row with NSStoryboardSegue - swift

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)
}

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)
}
}

Pass data to variable in swift

I want to assign button tag to variable. Then I trying send this data to SecondViewController and assign it to var.
#IBAction func goToProducts(_ sender: UIButton) {
performSegue(withIdentifier: TextStrings.ProfileAluVC.goToProducts, sender: self)
categoryNumber = sender.tag }
Pass data to ProductsViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToProducts" {
let destinationController = segue.destination as! ProductsViewController
destinationController.categoryNumb = categoryNumber
}
}
At ProductsViewController I create var but there isn't this data. I print this variable and I get this:
categoryNumber: 373
categoryNumb: Optional(24)
Can you tell me haw can I do this?
You need to assign it first before performSegue
categoryNumber = sender.tag
performSegue(withIdentifier: TextStrings.ProfileAluVC.goToProducts, sender: self)
OR use sender
performSegue(withIdentifier: TextStrings.ProfileAluVC.goToProducts, sender: sender.tag)
Pass data to ProductsViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToProducts" {
let destinationController = segue.destination as! ProductsViewController
destinationController.categoryNumb = sender as! Int
}
}

Two "performSegue" in same class to different Viewcontrollers

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.

Could not cast value of type 'Work.Login' (0x10c5edd20) to 'Work.DataBaseConn'

I have a problem with my second viewController when trying to send data with segue. The code of Login is:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let secondView = segue.destination as! DataBaseConn
secondView.user=TextUsername.text!
secondView.pass=Pass.text!
}
override func viewDidLoad() {
super.viewDidLoad()
self.performSegue(withIdentifier: "sendData", sender: self)
}
I get the error at this line:
let secondView = segue.destination as! DataBaseConn
Both views have the custom class set.

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.