Segue from an UITableViewController to another one issue - swift

I am trying to segue 2 ViewControllers of of UI Table type, but it shows me an error "Thread 1: signal SIGABRT", here the code:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showPlates"{
if let indexPath = self.tableView.indexPathForSelectedRow{
let selectedRecipe = self.recetas[indexPath.row]
let destinationViewController = segue.destination as! PlateViewController
destinationViewController.recetas = [selectedRecipe]
}
}
}

Probably you haven't set a class (PlateViewController) for desired destination ViewController in your storyboard (I guess in Main.storyboard)

Related

How to create segue for a view controller to another view controller which is embedded in a navigation controller?

This is how my storyboard is linked.
This is my segue function. Segue to priceViewController works fine, but to the other view controller keeps crashing. Receiving error 'Could not cast value of type 'UINavigationController' (0x11e264a20) to 'tableViewwithSections.priceViewController'.
Any help would be appreciated.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "toPriceView"){
let des = segue.destination as! priceViewController
des.currentCity = String(self.cityLabel.text!)
}
if(segue.identifier == "toTableView"){
let des = segue.destination as! tableViewController
des.currentCity = String(self.cityLabel.text!)
}
}
You had something like this originally and as far as I can see it should work. You need to access the tableViewController through the UINavigationController.
if(segue.identifier == "toTableView"){
let nc = segue.destination as! UINavigationController
let des = nc.topViewController! as! tableViewController
des.currentCity = String(cityLabel.text!)
}

Problem with cast on the function prepareForSegue

I have an error with my segue. When I click on the information button the application crashes. In the title View I have multiple segues. The first one is for send array to the register view and the others is for opening my information Pop Up.
The message error is:
And this is the main StoryBoard:
How do I fix this?
If you have 2 segues then you need to differentiate them with the identifier
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifer == "toPopUp" {
if let yourVC = segue.destination as? YourPopController {
// set data
}
}
else {
if let yourVC = segue.destination as? RegisterViewController {
// set data
}
}
}

(Swift) how to use Segue pass textField to TableViewCell under another ViewController?

I wonder how to pass the textField to my customTableViweCell. Please, someone help me! enter image description here
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segue" {
let nextVC = segue.destination as! UINavigationController
let dest = nextVC.topViewController as! ViewController
let ind = sender as! customTableViewCell
let nTxt = nameTxt.text?.description
let pTxt = phoneTxt.text?.description
let eTxt = emailTxt.text?.description
let dTxt = dobTxt.text?.description
ind.lb1 = "\(nTxt!)"
ind.lb2 = "\(pTxt!)"
ind.lb3 = "\(eTxt!)"
ind.lb4 = "\(dTxt!)"
}
}
segue.destination will contain the destination view controller. You should cast it to your custom view controller that will be presented. That view controller, should have properties defined that will be used to build that view. You should set those properties in prepare so that when the destination view controller loads the view, those properties can be used to update the view components. Here's an example.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segue" {
let dest = segue.destination as? YourCustomViewController
dest?.customProp = someValue
}
}

Difference Between 2 Ways of Declaring a ViewController Object

So I experimented with these 2 different ways of declaring a ViewController variable and it seemed to offer me the same results. However, I do feel there must be a difference between setting the destinationVC variable because if not, won't people use the more straightforward way of just declaring a new object?
[using segue.destination as! ViewControllerName]
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "changeCityName" {
let destinationVC = segue.destination as! ChangeCityViewController
destinationVC.delegate = self
}
}
[using ViewControllerName()]
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "changeCityName" {
let destinationVC = ChangeCityViewController()
destinationVC.delegate = self
}
}
In the prepareForSegue method, these two methods of creating a new VC differs greatly.
If you use segue.destination, you refer to the specific VC that the segue is going to, i.e. the one in your storyboard that the segue is connected to. If you create a new VC, then the VC you created won't be the same one as the segue is going to. i.e. you are dealing with a separate VC. Setting the delegate of the newly created VC won't do anything to the VC that is actually being presented.
If you are talking about the difference between using a segue to present a VC and this:
let vc = SomeViewController()
self.present(vc, animated: true)
Then the difference is less. If you use segues, then the views in the view controller will be read from the storyboard (NIB) file. If you create the VC by calling the initializer, you will have to handle adding the views in your view controller class.
Result may be visually same but its not true.
If you don't put any code inside prepare(for segue) still you will get same result(visually)
prepare(for segue) is called when UIViewControllers are connected through storyboard.
Since UIViewControllers are already connected in storyboard, so the destination UIViewController is called on your desired event.
In your first case using (segue.destination as! ViewControllerName) which is correct way of using segue.
Before going further one more thing is to be discussed about and that is
Why we are required to write code inside prepare(for segue) if its already connect through storyboard
1.From one button action you can connect several segues depending on your requirements, but each time button is pressed same prepare(for segue) method will be called, so to differentiate which UIViewController is to be called we do something like this
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "FirstViewControllerIdentifier")
{
}else if(segue.identifier == "SecondViewControllerIdentifier"){
}else if(segue.identifier == "ThirdViewControllerIdentifier"){
}else{
// and so no
}
}
Now here we get object of destination controller(UIViewController) already being prepared.So we are not required to make a new object of destination controller
2.We can pass data to destination controller and also we can set delegate
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "FirstViewControllerIdentifier")
{
// here we get object of first view controller and set delegate
let firstVC = segue.destination as! FirstViewController
firstVC.delegate = self
}else if(segue.identifier == "SecondViewControllerIdentifier"){
// here we get object of second view controller and pass some data to it
let secondVC = segue.destination as! SecondViewController
secondVC.someData = someData
}else if(segue.identifier == "ThirdViewControllerIdentifier"){
}else{
// and so no
}
}
Now in your second case using ViewControllerName() (the wrong code)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "FirstViewControllerIdentifier")
{
// here we create object of first view controller.This object is different from the destination view controller
//you create an object and set a delegate but after that you are not using that object and that object is totallu useless.
let firstVC = FirstViewController()
firstVC.delegate = self
// above code does not affect any thing but the contoller which is to be presented is destination view controller which is connected through storyboard
}
}
Hope you understand how to use segue and let me know if there is any problem

Accessing methods, actions and/or outlets from other controllers with swift

I'm working on a macOS project where I have a split view containing 2 other ViewControllers and I can't figure out how to access the ViewControllers from my primary window's ViewController.
this is the setup:
Basically what I'm trying to do is use the Button in my ViewController on the top-left to access the Label in my SectionController on the right, which is embedded in my split view.
Since I can't create an IBAction or IBOutlet for a control in a different ViewController, I can't figure out how to get these to be connected. My current workaround has been to have a property on my AppDelegate and then access the main shared application delegate, but that feels hacky and won't scale. I'm completely lost as to how to proceed. I'm ok with using a function to pass data or whatever to the other ViewController(s).
I'm using Swift 4 with Xcode 9 (beta).
Any ideas?
Of course you can't create IBAction or IBOutlet for a control in a different ViewController!!
But simply each view controller in the hierarchy has a reference for its child view controllers.
Method 1:
#IBAction func buttonTapped(_ sender: Any) {
let splitViewController = self.childViewControllers[0] as! YourSplitViewController
let targetViewController = splitViewController.childViewControllers[0] as! YourTargetViewController
targetViewController.label.text = "Whatever!"
}
Method 2:
It may be better if you took a reference for each child controller in your "prepare for segue" method
ContainerViewController:
var mySplitViewController: YourSplitViewController?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "splitViewSegue" {
self.mySplitViewController = segue.destination as! YourSplitViewController
}
}
YourSplitViewController:
var aViewController: YourFirstViewController?
var bViewController: YourSecondViewController?
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "aViewSegue" {
self.aViewController = segue.destination as! YourFirstViewController
} else if segue.identifier == "bViewSegue" {
self.bViewController = segue.destination as! YourSecondViewController
}
}
So you can access it like that in your container view controller:
#IBAction func buttonTapped(_ sender: Any) {
self.mySplitViewController.firstViewController.label.text = "Whatever!"
}