Receiver has no segue with identifier 'goToDetail' - ios

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

Related

Dismiss my view controller but "prepare" the view controller underneath

I have a modally-presented ViewController that has a UITableView inside it. When the user clicks "Days", it shows this view controller (modally). Here's my Storyboard:
What I want to do is, when I click one of the cells in the table view in the modal, I want to dismiss the modal, but also load new data in the root view controller.
How can I have access to the root view controller from a segued view controller?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.dismiss(animated: true, completion: nil)
}
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinationVC = segue.destination as! DayView
if let indexPath = tableView.indexPathForSelectedRow {
destinationVC.day = days![indexPath.row]
}
}
I want something like what I've written above, but while my modal does get dismissed, but what I want is for somehow the code in the prepare function to fire when a TableViewCell is clicked.
A shorter and simpler method than protocol/delegate is to create a closure:
For sending a String back, In First ViewController:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let viewControllerB = segue.destination as? ViewControllerB {
viewControllerB.callback = { message in
//Do what you want in here!
}
}
}
In ViewControllerB:
var callback : ((String) -> Void)?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
callback?("Your Data")
self.dismiss(animated: true, completion: nil)
}
you are in the right path,you need to add two more functions 1. unwindsegue and one this is not destination its source so you need change to source from destination.
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let destinationVC = segue.source as! DayView
if let indexPath = tableView.indexPathForSelectedRow {
destinationVC.day = days![indexPath.row]
}
}
for Reference : How to Pass Data in an Unwind Segue

performSegue view not in window hierarchy

I'm trying to perform a segue to another view controller with this code:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
placemarkIndex = indexPath.row
self.view.endEditing(true)
self.dismiss(animated: true, completion: nil)
self.performSegue(withIdentifier: K.Segues.cityViewController, sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == K.Segues.cityViewController {
let destinationVC = segue.destination as! CityViewController
if let index = placemarkIndex, let city = cities?[index] {
destinationVC.location = city
}
}
}
the segue works when I search the table view and select the row while searching, however, it returns the following error when clicking on a row without searching action enabled:
Warning: Attempt to present <Simple_Forecast.CityViewController: 0x7fadc9893a00> on <Simple_Forecast.SearchViewController: 0x7fadcc12f390> whose view is not in the window hierarchy!
How can I solve this?
Thank you

Unwind Segue with Image

I'm trying to use a unwind Segue with an ImageView. In my main VC I created this function for the unwind segue:
#IBAction func didUnwindFromSelectIcon(_ sender: UIStoryboardSegue){
guard let imageSelectionImage = sender.source as? SelectIconViewController else {return}
addEatImageViewEat.image = imageSelectionImage.img
}
Then I use this in my second VC
var img: UIImage?
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedImage = collectionView.cellForItem(at: indexPath) as! SelectIconCollectionViewCell
img = selectedImage.selectIconImageView.image
}
I selected the didUnwindFromSelectIcon at the CollectionViewCell on the Storyboard. I get no error or something and I'm not sure what my mistake is. My addEatImageViewEat won't show my selected Image... Hope someone see what's my mistake - Thanks in advance
Update:
MainVC:
#IBAction func didUnwindFromSelectIcon(_ sender: UIStoryboardSegue){
guard let imageSelectionImage = sender.source as? SelectIconViewController else {return}
addEatImageViewEat.image = imageSelectionImage.img
}
SecondVC:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "unwindSegue" {
if let cell = sender as? SelectIconCollectionViewCell {
img = cell.selectIconImageView.image
}
}
}
The problem is that the segue happens before func collectionView(_:didSelectItemAt:) is called.
Instead of using that function, use prepare(for:sender:) to set the image:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "unwindSegue" {
if let cell = sender as? SelectIconCollectionViewCell {
img = cell.selectIconImageView.image
}
}
}
Make sure to set the identifier for your segue and use that in place of "unwindSegue" above. To set the segue identifier, find the unwind segue in the Document Outline view and select it. Then in the Attributes Inspector on the right, set the Storyboard Segue Identifier to your identifier.

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

managing page navigation at swift2

I'm trying to learn page navigation without using "Navigation Controller".
Created a button and function like;
#IBAction func backPressed(sender: AnyObject) {
self.performSegueWithIdentifier("page2ToMain", sender: self)
}
It works fine.
I need to pass data from page 2 to page 3. So, inside "didSelectRowAtIndexPath" I used "performSegueWithIdentifier" and override "prepareForSegue" function as below;
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.selectedRow = self.dataArray[indexPath.row]
self.performSegueWithIdentifier("page2ToPage3", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let nextViewController = segue.destinationViewController as! ViewController3
nextViewController.data = self.selectedRow
print(self.selectedRow)
}
When I click the table cell it works well, jumps to other view controller and I see data variable.
But when I press back button it fails with;
Could not cast value of type 'test3.ViewControllerMain' (0x1045469f0) to 'test3.ViewController3' (0x1045466e0).
How can I solve the problem?
You can test for this with optional binding:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let nextViewController = segue.destinationViewController as? ViewController3 {
nextViewController.data = self.selectedRow
print(self.selectedRow)
}
}
Or look at the segue identifier and then test for that:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "page2ToPage3" {
let nextViewController = segue.destinationViewController as! ViewController3
nextViewController.data = self.selectedRow
print(self.selectedRow)
}
}

Resources