Prepare for Segue: one VC to another VC with optionals? - swift

I have one variable, usernameSelected, that I want to send to a second VC.
First VC:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let usernameSelectedRow = picUsernameArray[indexPath.row]
usernameSelected = usernameSelectedRow
print(usernameSelectedRow) --> [this prints the right data]
print(usernameSelected) --> [this prints the right data]
performSegue(withIdentifier: "goToProfileSelected", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToProfileSelected" {
let destination = segue.destination as?
OtherUserProfileViewController
print(usernameSelected) ---> [this prints nil!!!!]
destination!.usernameValue = usernameSelected ---> [this returns nil to second VC]
}
}

in did select:
self.performSegue(withIdentifier: "goToProfileSelected", sender: indexPath) //pass indexPath
now in prepare for segue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let index = sender as? IndexPath {
let name = self.picUsernameArray[index.row]
destination.usernameValue = name
}
}

Related

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

Error within tableView when swapping detailView for a different view

I have the function
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let indexPath = tableView.indexPathForSelectedRow {
let object = dailyAgenda[indexPath.row]
if object == "Time Management" {
self.performSegue(withIdentifier: "showTimeManagement", sender: self)
}
else {
self.performSegue(withIdentifier: "showDetail", sender: self)
}}}
And the prepare for segue function
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail" {
if let indexPath = tableView.indexPathForSelectedRow {
let object = dailyAgenda[indexPath.row]
var controller = (segue.destination as! UINavigationController).topViewController as! DetailViewController
controller.detailItem = object
controller.textDescription = indepthDescript[indexPath.row]
}}
if segue.identifier == "showTimeManagement" {
var controller = (segue.destination as! UINavigationController).topViewController as! TimeManagement
}
}
But I keep getting the error "Thread 1: Fatal error: Index out of range" when selecting the cell that performs the showTimeManagement segue. The error occurs on the "controller.textDescription = indepthDescript[indexPath.row]]" line within the showDetail segue. Why would it even be running this line in the first place and where am I going wrong?

Prepare for segue not passing data

I'm working on a Swift project using firebase and I have a UICollectionViewController that has all the categories, and I need to pass the category Id to the next view, but It passes an empty string
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let category = cnameArray[indexPath.row]
let catId = category.caId
func prepare(for segue: UIStoryboardSegue, sender: Any?){
if segue.identifier == "CatCity" {
let cityView = segue.destination as? CityViewController
cityView?.catId = catId!
} }
self.performSegue(withIdentifier: "CatCity", sender: self)
}
and in my CityViewController I have
var catId = String()
when I put a break point at the last line of the prepare func it gets hit and the console gets the value correctly while sitting a breakpoint at CityViewController gives me an empty var.
and I checked the code and my segue name and everything looks fine!
Correct setup
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let category = cnameArray[indexPath.row]
self.performSegue(withIdentifier: "CatCity", sender: category.caId)
}
func prepare(for segue: UIStoryboardSegue, sender: Any?){
if segue.identifier == "CatCity" {
if let cityView = segue.destination as? CityViewController {
cityView.catId = sender as! String
}
}
}

PrepareForSegue not sending data between two TableView Controllers

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!

Prepareforsegue not passing the appropriate value to destination Viewcontroller?

I have two viewcontrollers (one is tableVC) that I would like to pass information between. Here is code from that tableVC:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var rowSelected = indexPath.row
print(rowSelected) //always returns the correct integer
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let destViewController: newController = segue.destination as! newController
newController.rowSelected = rowSelected
}
performSegue(withIdentifier: "rowSelected", sender: Any?.self)//segue to newController
}
And here is the code for the newController that I want the info to be passed to:
#IBOutlet weak var label: UILabel!
var rowSelected = Int()
override func viewDidLoad() {
super.viewDidLoad()
label.text = infoArray[rowSelected]
print(rowSelected) //always logs 0 to the console, regardless of cell selection
}
I thought I had set this up appropriately, but for whatever reason the index called to the infoArray is always 0, no matter what cell is selected in the tableVC. Not sure what the problem is.
write prepareForSegue in class scope/global scope. in your code prepareForSegue will never call because you are writing this inside the method. pass rowSelected in performSegue and get rowSelected value in prepareForSegue using sender or you can use indexPathForSelectedRow property of tableView.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
...
performSegue(withIdentifier: "rowSelected", sender: rowSelected)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: Any?) {
let rowSelected = sender as! Int
// or you can use indexPathForSelectedRow for getting row value
// let indexPath = self.tableView.indexPathForSelectedRow?
// let rowSelected = indexPath!.row
let destViewController: newController = segue.destination as! newController
newController.rowSelected = rowSelected
}
Need to use override in your function when you prepareForSegue
See below example code : -
Swift 3
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ShowAttractionDetails" {
let detailViewController = segue.destination
as! AttractionDetailViewController
let myIndexPath = self.tableView.indexPathForSelectedRow!
let row = myIndexPath.row
detailViewController.webSite = webAddresses[row]
}
}
Swift 2.3
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "ShowAttractionDetails" {
let detailViewController = segue.destination
as! AttractionDetailViewController
let myIndexPath = self.tableView.indexPathForSelectedRow!
let row = myIndexPath.row
detailViewController.webSite = webAddresses[row]
}
}
Source - Segue from UITableViewCell Taps in Swift & TableView Navigation using Storyboards in Xcode 8