IOS/Swift: Pass Object in tableview to detail view controller - ios

I am trying to grab an object from a tableview and pass it to a detail view, something I know how to do in Objective-C but am learning for first time Swift. However, my code is not getting the row from the index path or object.
Here is my code.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
print("segue")
if segue.identifier == "showDetail"{
if let destinationVC = segue.destination as? detailVC {
)
if let indexPath = self.tableView.indexPathForSelectedRow {
print("row%#",indexPath)//Prints as nil
let thisItem = myItems[indexPath.row]//never gets here
destinationVC.item = thisItem
}
}
}
}
Can anyone see why I am not getting the row or the object? Thanks in advance for any suggestions.
Edit:
I got it to work with following:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail" {
let indexPath: NSIndexPath = self.tableView.indexPathForSelectedRow! as NSIndexPath
let anItem: myItem = myItems[indexPath.row];
let destVC = segue.destination as? detailVC
destVC?.item = anItem
}
}

Implement UITableViewDelegate method,
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = myItems[indexPath.row]
self.performSegue(withIdentifier: "showDetail", sender: item)
}
then implement below,
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showdetail" {
let detailController = segue.destination as! detailVC
detailController.item = sender as! Your_Item
}
}

Why don't you use these methods to save the value of the selected row or item? and then perform segue?
tableView(_:didDeselectRowAt:)
tableView(_:didSelectRowAt:)

Related

Set a string as a var after selecting a UITableView cell in Swift 3

I am making an audio app, and I am populating a table view controller with data from JSON. Based on the user's selection, I want to pass the episode_name, shown in the cell, into the next view after segue.
So far, the table loads with data, I can pass a locally defined variable to the next view, but I can't copy the string from the cell into that variable.
Here's my code.
func extract_json(_ data: Data)
{
//... removed to condense
if let shows_list = json as? NSArray
{
for i in 0 ..< data_list.count
{
if let shows_obj = shows_list[i] as? NSDictionary
{
let episode_name = shows_obj["episode"] as? String
let episode_date = shows_obj["date"] as? String
TableData.append(episode_date! + " | " + episode_name!)
}
}
}
DispatchQueue.main.async(execute: {self.do_table_refresh()})
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "passer", sender: indexPath)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "passer" {
let vc = segue.destination as! EpisodeViewController
vc.variableInSecondVc = "Pass Variable" // this is where I want to pass episode_name
}
} // end segue
Solutions I have tried:
1) if I call episode_name immediately, it flags it because that variable is contained in the prior function,
2) if I try to run the extract_json function in the ViewDidLoad, it's causing other issues in the code.
I'm new to Swift and unsure -- is there a better way to "copy" the string from that cell and pass it to the vc.variableInSecondVc?
EDIT: One point of clarification. If I ran this code, it would successfully change the subsequent UILabel to "Pass Variable" -- but of course, I actually want to turn PassVariable dynamic by changing it to reflect the string of episode_name.
The performSegue(withIdentifier:sender:) method takes two arguments, 1. The Segue identifier, 2. The parameter you want to pass of type AnyObject?
self.performSegue(withIdentifier: "passer", sender: indexPath)
In the prepare(for:sender:) method, you check the segue identifier and cast the sender parameter to the type you had passed earlier, and get data from the array list to pass it to next view controller.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "passer" {
guard let indexPath = sender as? IndexPath else { return }
let data = TableData[indexPath.row] //write your logic here to get value from your data list based on index path row value and pass value to view controller.
let vc = segue.destination as! EpisodeViewController
vc.variableInSecondVc = data //value which you got from list based on indexPath
}
}
Get data from indexPath
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "passer" {
let vc = segue.destination as! EpisodeViewController
vc.variableInSecondVc = TableData[indexPath.row]
}
}
And carefully, you should get the string in viewDidAppear in secondViewController
override func viewDidAppear() {
label.text = variableInSecondVc
}
Thanks for the help, all.
While these solutions didn't work, they helped me rethink the problem, and I found a solution that will pass the value to the label in the next VC successfully. Here's the approach:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "passer", sender: indexPath)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let indexPath = self.tableView.indexPathForSelectedRow {
let controller = segue.destination as! EpisodeViewController
controller.variableInSecondVc = TableData[indexPath.row]
}
}
The label now updates in the next view controller.
try this it will send the selected string to next View controller
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "passer" , let indexPath = sender as? IndexPath{
let vc = segue.destination as! EpisodeViewController
vc.variableInSecondVc = TableData[indexPath.row]
}
}

Passing data to next view controller, but data disappears?

I have a tableview with cells that each contain a "Concept", CoreData Object. They all have an attribute called html, which are not nil (I checked that by printing in this tableview viewDidLoad()). The problem is when I try to pass it in prepareForSegue this data kind of disappears.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let indexPath = tableView.indexPathForSelectedRow
if segue.identifier == "toConcept"{
let nc = segue.destination as! UINavigationController
let vc = nc.viewControllers.first as! PDFViewController
print(concepts[(indexPath?.row)!].html
//This prints nothing.
vc.html = concepts[(indexPath?.row)!].html
}
}
The problem is in the viewDidLoad() the html is fine and not nothing, but in the prepareForSegue is prints nothing and in the PDFViewController it is also gone.
Does anybody know how to fix this?
try this..
func tableView(_ messagesListTableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "toConcept", sender: indexPath)
print(indexPath)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toConcept"{
let indexPath = sender as? IndexPath
let nc = segue.destination as! UINavigationController
let vc = nc.viewControllers.first as! PDFViewController
print(concepts[(indexPath?.row)!].html
//This prints nothing.
vc.html = concepts[(indexPath?.row)!].html
}
}

Passing data from table view controller to view controller

I'm having issues with moving from a table view controller to a view controller to display information about a particular cell that was selected.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "SentDetailView" {
let indexPath: NSIndexPath = self.tableView.indexPathForSelectedRow! as NSIndexPath
let referrals = referralsSent[indexPath.row]
let destViewController = segue.destination as! SentDetailViewController
destViewController.referringTo = referrals.referTo
destViewController.patientsName = referrals.patientsName
//print("Contained value during segue " + destViewController.patientsName!)
destViewController.patientsPhoneNumber = referrals.patientsNumber
destViewController.patientsEmail = referrals.patientsEmail
destViewController.comments = referrals.comment
}
}
Storyboard setup:
I get the following results:
I select a cell and it just highlights and doesn't do anything.
You should override didSelectRowAt and call performSegue with sender as the selected index path. Try this.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "SentDetailView", sender: indexPath)
}
And this.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "SentDetailView"{
let indexPath = sender as! IndexPath
let referrals = referralsSent[indexPath.row]
let destViewController = segue.destination as! SentDetailViewController
destViewController.referringTo = referrals.referTo
destViewController.patientsName = referrals.patientsName
//print("Contained value during segue " + destViewController.patientsName!)
destViewController.patientsPhoneNumber = referrals.patientsNumber
destViewController.patientsEmail = referrals.patientsEmail
destViewController.comments = referrals.comment
}
}

Usage of performSeguewithIdentifier Function in Dynamic Values Tableview

I can list datas in tableview. When I choose a row and trying to pass another view controller with showing specific data related to my pressed cell, It couldn't make it.
I didn't able to store data "selectedMeal" variable in prepareforsegue function, it always return [ ].
I think, my main problem is selecting the cell and sending to this cell to prepare for segue function. Perhaps, it has a problem in DispatchQueue.main.async function.
*When I try to pass to static data, it works great.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
cell.accessoryType = .checkmark;
DispatchQueue.main.async {
self.performSegue(withIdentifier: "gotoOrderDetail", sender: self)
}
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "gotoOrderDetail") {
let DestViewController : OrderDetailListViewController = segue.destination as! OrderDetailListViewController
let selectedMeal = selectedCells.map { (index: Int) -> SavedMeal in
return savedMeal[index]
}
DestViewController.mealarray = selectedMeal
}
}
Try to use this code
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "gotoOrderDetail") {
let DestViewController : OrderDetailListViewController = segue.destination as! OrderDetailListViewController
let path = self.tableView.indexPathForSelectedRow()! // get the selected indexPath
DestViewController.mealarray = savedMeal[path.row]
}
}
Try to use Sender parameter
you can you like this:
self.performSegue(withIdentifier: "gotoOrderDetail", sender: indexPath)
and then in prepare(for segue: sender?)
if (segue.identifier == "gotoOrderDetail") {
let DestViewController : OrderDetailListViewController = segue.destination as! OrderDetailListViewController
let index = sender as! Int
DestViewController.mealarray = savedMeal[index]
}
p/s: you do not need to use dispatch queue in this case

prepareForSegue UICollectionView not working (swift)

I’ve tried to push segue by using UICollectionView (show image form MasterView to DeatilView) but is not working. Xcode also doesn’t show any error message. What’s wrong with my code. I need some advice.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDetail" {
if let indexPath = self.collectionView?.indexPathForCell(sender as! UICollectionViewCell) {
let detailVC = segue.destinationViewController as! DetailMenuViewController
detailVC.picFood = self.collection[indexPath.row]
collection is empty array get data form json
[title = self.nameFood.title], it is working in DetailMenuViewController.swift but not image on code above.
You need to add the UICollecitonViewDelegate
func collectionView(collection: UICollectionView, selectedItemIndex: NSIndexPath)
{
self.performSegueWithIdentifier("showDetail", sender: self)
}
After that add
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDetail" {
if let indexPath = self.collectionView?.indexPathForCell(sender as! UICollectionViewCell) {
let detailVC = segue.destinationViewController as! DetailMenuViewController
detailVC.picFood = self.collection[indexPath.row]
}
}
}

Resources