passing data between controllers shows an error - ios

I've put a navigation controller in between viewcontrollers according to my project. When I tried to pass the data its shows the following error:
Could not cast value of type 'UINavigationController' (0x10900b008) to 'uday.Food_Drinks_DetailTableViewController' (0x105b72600).
This is my code:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "fdShow", sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "fdShow"{
if let indexpath = tablevi.indexPathForSelectedRow {
let fddVc = segue.destination as! Food_Drinks_DetailTableViewController
fddVc.FdString = fad[indexpath.row]
}
}
}
I'm getting the error at the following line:
let fddVc = segue.destination as! Food_Drinks_DetailTableViewController

I think your segue destination is UINavigationController.If you are not using custom class for navigation controller. You need to change code to
let navVc = segue.destination as! UINavigationController
and then, if Food_Drinks_DetailTableViewController is the first controller in navigation controller
let fddVc = navVc.viewControllers.first as! Food_Drinks_DetailTableViewController
fddVc.FdString = fad[indexpath.row]

Related

Receiver has no segue with identifier 'goToDetail'

I've double-checked that my identifier is spelled correctly in the storyboard and that the segue is pointed in the right direction, but I keep receiving this error. Could someone take a look at my code to see if I'm missing something?
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedData = tableData[indexPath.row]
tableView.deselectRow(at: indexPath, animated: true)
performSegue(withIdentifier: "goToDetail", sender: selectedData)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? DetailViewController {
destination.vocab.text = sender as? String
}
}
Edit:
segue can be used only with if you have a UINavigationController that will handle the navigation. You performing a segue to UINavigationController. UINavigationController should be at the root of your storyboard.
In your didSelectRowAt function change
performSegue(withIdentifier: "goToDetail", sender: selectedData)
To NavigationController Identifier (Note if you do not have identifier already set up in storyboard you will need to do that first)
performSegue(withIdentifier: "goToNavigationConrtoller", sender: selectedData)
And then change the prepareForSegue function to below.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//check destination for segue is Navigation controller
if let navVC = segue.destinationViewController as? UINavigationController {
// get hold of the first viewController.
if let destination = navVC.viewControllers[0] as? DetailViewController {
destination.vocab.text = sender as? String
//all the other code you need
}
}
}

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 cell to new view controller error

I'm trying to pass data from my tableViewCell, however, keep getting an error on my let cell = sender as! UITableViewCell
fatal error: unexpectedly found nil while unwrapping an Optional
value.
How would I make my cell an optional? I'm trying to pass the data from an array.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? UsersProfileViewController{
let cell = sender as! UITableViewCell
let selectedRow = partnerTable.indexPath(for: cell)?.row
if let name = usersArray[selectedRow!].firstLastName{
destination.name = name
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "toUser", sender: nil)
}
}
You should trigger this way
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "toUser", sender: indexPath.row)
}
and in prepare for segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
let selectedRow = sender as? Int
if let name = usersArray[selectedRow!].firstLastName{
destination.name = name
}
}
If you prefer to use segue using storyboard:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let indexPath = tableView.indexPathForSelectedRow {
guard let destinationVC = segue.destination as? UsersProfileViewController else {return}
let selectedRow = indexPath.row
destinationVC.name = usersArray[selectedRow].firstLastName
}
}
You can also segue to the destination ViewController programatically and pass the required value to that Controller.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let sb = UIStoryboard.init(name: "StoryboardName", bundle: nil)
let destinationVC = sb.instantiateViewController(
withIdentifier: "StoryboardId for viewcontroller set in storyboard") as? UsersProfileViewController
guard let name = usersArray[selectedRow!].firstLastName { else return }
destinationVC.name = name
self.presentViewController(destinationVC, animated: true, completion: nil)
}
Steps:
Get an instance of the storyboard.
Instantiate the required viewcontroller with the help of storyboard Id which is assigned in the storyboard.
Pass the data required to destination VC.
Present the destination View Controller.
I got one thing from you post, you want to get current selected tableview data and want to pass it to next view controller, you can do this in a simple way. Check tableview cell selected delegate method
didSelectRowAtIndexPath
From this delegate method you can save selected row index and in prepare segue method call this function in this way , selectedRow value you can set in didSelectRowAtIndexPath delegate method.
usersArray[selectedRow!].firstLastName
Steps To Do:
First of all create the property selectedIndex in View controller.
set the selectedIndex property value with indexPath from didSelectRowAtIndexPath table view's delegate methods.
In Prepare for Segue method you can find the data value from your datasource object as you have selected index.
4.Pass the value from datasource for selected index and make selectedIndex property to nil.

Ambiguous reference to member 'tableView(_:numberOfRowsInSection:)' Why this error?

Here is my code in which the error appears:
The error is in line 3 'if let indexpath...'
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "show Detail" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let taakDetail : Taak = taken[(indexPath as NSIndexPath).row]
let controller = (segue.destination as! UINavigationController).topViewController as! DetailsViewController
controller.selectedTaak = taakDetail
}
}
I can't find out what is ambiguous about this. The code to which it refers to is:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return taken.count
}
It's not finding tableView, and is therefore getting thrown off, assuming you somehow meant to reference this method (which you don't, obviously).
Note, your outlet is tableview, not tableView. Properties are case sensitive.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "show Detail" {
if let indexPath = self.tableview.indexPathForSelectedRow {
let taakDetail : Taak = taken[indexPath.row]
let controller = (segue.destination as! UINavigationController).topViewController as! DetailsViewController
controller.selectedTaak = taakDetail
}
}
}

Resources