PrepareForSegue not sending data between two TableView Controllers - swift

I am trying to pass a test variable to my destination controller, but the test is unsuccessful.
My performsegue is done here:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
programKeySegue = programKeys[indexPath.section]
self.performSegue(withIdentifier: "segueSelectedProgram", sender: self)
}
My prepareforsegue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segueSelectedProgam" {
let selectedProgramVC = segue.destination as! SelectedProgramTableViewController
selectedProgramVC.programKey = "test" //programKeySegue
}
}
and in the destination controller:
var programKey: String?
But when I print(programKey) in viewDidLoad 'nil' is printed to the console. I have used this method before and it has always worked fine. Can anyone tell me what I did wrong?
I tired removing override from prepare for segue, I tried appending self to the performsegue and I have tried assigning different variables to be passed. Nothing has worked.

As noted in the comments, your problem was caused by a typo. You can prevent this in future by not using string comparison…
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// If there are multiple segues to this destination, you can
// perform a similar check on the source
if let selectedProgramVC = segue.destination as? SelectedProgramTableViewController
selectedProgramVC.programKey = "test" //programKeySegue
}
}
Also, you could give use the view controller name as the segue name in the storyboard, and then…
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
programKeySegue = programKeys[indexPath.section]
self.performSegue(withIdentifier: String(describing: SelectedProgramTableViewController .self), sender: self)
}
et voila… no strings!

Related

With swift5 no longer works indexPathForSelectedRow is not recognized by xcode

With swift5 and TableView (no TableViewController), no longer works indexPathForSelectedRow is not recognized by xcode, I don't know what has changed
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "goToItems", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinationVC = segue.destination as! ViewController2
if let indexPath = tableView.indexPathForSelectedRow {
destinationVC.selectedTable = dataTableWord[indexPath.row]
} else {
}
}
There is no change on the UITableView on swift5 or Xcode.
Make sure that you have defined your UITableView variable correctly.
Or, if you're using storyboard, remove and reconnect your tableView outlet to the UITableView object on the storyboard.

Im trying to perform a segue but cant grab the selected cell info with an IBaction and cellForRowAt is not registering

I'm trying to perform a segue and want to use the text of the selected cell to control what information is displayed on the new screen. I can use the IBaction to perform the segue but as yet can't figure out how to grab the cell info. So I then tried using
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) and didselectrowat but neither are working. I have tried removing the IBaction and deleting the button which gets rid of the Invalid argument NSexception fault but when I click on the cell absolutely nothing.
Ive included my code and in its current form the segue does happen albeit with no info displayed . If I delete the IBaction line and remove the button from the storyboard then nothing. Please point me in the right direction.
// func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
#IBAction func segueToDriverRDWList(_ sender: UIButton) {
print("SEGUE")
performSegue(withIdentifier: "gotodriverRDWlist", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinationVC = segue.destination as! DriverRDWViewController
// destinationVC.selectedDriver = driverNameArray[indexPath.row]
// print(driverNameArray[indexPath.row])
}
As per my knowledge you haven't confirmed datasource and delegate method of UItableview, that's why didselect method were not working. Please refer this for more details
https://shrikar.com/uitableview-delegate-and-datasource-in-swift/#:~:text=Create%20a%20new%20file%20called%20MainViewController.,the%20UITableViewDataSource%20and%20UITableViewDelegate%20Protocol.&text=numberOfRowsInSection%20will%20tell%20how%20many,tableview%20for%20that%20particular%20section.
You don't need an #IBAction, just use the didSelectRowAt, and your class must conform to the UITableViewDelegate & UITableViewDataSource protocols (dataSource and delegate must be set as self as well) :
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "gotodriverRDWlist" {
let destinationVC = segue.destination as! DriverRDWViewController
//Pass your data here
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "gotodriverRDWlist", sender: nil)
}

Swift Prepare(for: segue) not called

In my storyboard controller1 has natigationController and segues to controller 2. It is weird that the Segue works ok but
override func prepare(for: segue)
the whole method was not called (I set breakpoint). I reviewed a lot of old questions on stackoverflow, but no one could solve my problem. Thanks!
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
self.navigationController?.performSegue(withIdentifier: segueId, sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == self.segueId {
let destionationNVC = segue.destination as! UINavigationController
guard let targetVC = destionationNVC.topViewController as? ViewController2 else { return }
targetVC.text = self.text
}
}
You are calling performSegue on self.navigationController, so it's the navigationController.prepareForSegue that will be called, not the one in your VC. You should reconnect the segue to your VC in the storyboard, give it the identifier, and call:
self.performSegue(...)

Swift - performSegue causing ViewController to load before prepareForSegue passes data

I'm trying to perform a segue between two table views via tapping on a cell. However it seems performSegue is loading the view before prepareForSegue has passed the data and thus the array is left empty in the second view controller.
Here's the code for my segue:
func prepare(for segue: UIStoryboardSegue, sender: Any?, didSelectRowAt indexPath: IndexPath) {
if let vc = segue.destination as? ModuleTableViewController {
vc.modules = programmes[indexPath.row].modules
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "ProgrammeToggleVCtoModuleVC", sender: self)
}
I'd like to have it pass across the data before the view is loaded, as there is a check in the second VC that causes the programme to crash if the data isn't present.
I've only been doing Swift for the past few weeks so excuse me if I've missed any info, happy to amend it if you need more information.
You need to hook segue from the vc itself not from the cell and correct prepare to
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? ModuleTableViewController {
vc.modules = programmes[tableView.indexPathForSelectedRow!.row].modules
}
}
OR
performSegue(withIdentifier: "ProgrammeToggleVCtoModuleVC", sender: indexPath.row)
with
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? ModuleTableViewController {
vc.modules = programmes[sender as! Int].modules
}
}

Segue not getting selected row number

I am passing data from a table view controller to a detail view. I tried using indexPath.row directly in my prepareForSegue method, however it displays an error of
use of unresolved identifier 'indexPath'
So, after searching the web, I set up the variable indexOfSelectedPerson which is assigned the value of indexPath.row. The problem when I run the app in the simulator is that prepareForSegue is getting the initial value of indexOfSelectedPerson (0), then getting the value of the selected row only after I click it. So, when I hit the back button in the Simulator and select a different row, the detail view shows the info of the row I selected the previous time.
import UIKit
class MasterTableViewController: UITableViewController {
var people = []
var indexOfSelectedPerson = 0
override func viewDidLoad() {
super.viewDidLoad()
people = ["Bob", "Doug", "Jill"]
}
override func numberOfSectionsInTableView(tableView: UITableView?) -> Int {
return 1
}
override func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int {
return people.count
}
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell = tableView!.dequeueReusableCellWithIdentifier("personCell", forIndexPath: indexPath) as UITableViewCell
cell.text = "\(people[indexPath.row])"
return cell
}
override func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!)
{
indexOfSelectedPerson = indexPath.row
}
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if let mySegue = segue.identifier {
if mySegue == "personDetails" {
let detailsVC: DetailTableViewController = segue.destinationViewController as DetailTableViewController
detailsVC.selectedPersonName = "\(people[indexOfSelectedPerson])"
}
}
}
}
So, selecting Doug when the app first starts in the simulator displays the details for Bob because indexPathOfSelectedPerson is 0. Hitting the back button and then selecting Jill displays the details for Doug because indexPathOfSelectedPerson became 1 when I clicked on Doug the previous time. I'm guessing the problem stems from the order in which the methods are called.
The best way to do this kind of thing is not to use the delegate.
Updated Swift 4+
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let selectedIndex = tableView.indexPath(for: sender as! UITableViewCell)
// Do your stuff with selectedIndex.row as the index
}
Original Answer
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
let selectedIndex = self.tableView.indexPathForCell(sender as UITableViewCell)
// Do your stuff with selectedIndex.row as the index
}
Swift 3 update:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let selectedIndex = tableView.indexPath(for: sender as! UITableViewCell)!
// Do your actual preparing here...
}
//In didSelectRowAtIndexPath, you use this code:
func tableView(tvMain: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("yourSegueName", sender: nil)
}
//And prepareForSegue to get IndexPath and send your value
override func prepareForSegue(segue: UIStoryboardSegue,
sender: AnyObject!){
let indexPath : NSIndexPath = self.yourTableView.indexPathForSelectedRow()!
//make sure that the segue is going to secondViewController
let detailsVC = segue.destinationViewController as DetailTableViewController
detailsVC.selectedPersonName = "\(people[indexPath.row])"
}