UIButton Triggering Segue - xcode

I am trying to link together 2 controllers with segue. I have a view controller with 6 button that after the click on a button will show a tableviewcontroller. I made all the link, give the identifier to segue etc.
in the tableviewcontroller there is an array that should show filtered results depending on which button trigger the segue
How should I write the prepareforsegue method?
This is what i am doing
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "chooseBrand" {
if sender?.tag == 1 {
let destinationController = segue.destinationViewController as! SelectionTableViewController
let numberOfCameras = destinationController.Camera.count
}
the problem is that i receive this error message
"Could not cast value of type 'UINavigationController' (0x10a0ef588)
to 'myApp.SelectionTableViewController' (0x108658b90)."
How can I define the content of the tableview in the selectiontableviewcontroller depending on which button is pressed?
Thanks a lot for any kind of help :)

What exactly is the sender here? The error is saying that sender with tag = 1 is not a SelectionTableViewController.
Anyway, what you could do is simply to connect each button to the same action outlet method and the have a generic segue between the two controllers. When you then hit button A, B, C, D, E, or F you simply check their tag(or store them as variables in your controller class) and send whatever you want to the controller. It's important that the segue you have between the controllers is between two controllers and not a segue from each UIButton the other controller. In the example below I assume you store each of the six UIButton as class variables.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "segueFromFirstToSecond" {
let destinationController = segue.destinationViewController as! SelectionTableViewController
if sender = button1 {
let numberOfCameras = destinationController.Camera.count
} else if sender == button2 {
let numberOfCameras = destinationController.Camera.count
}
}
#IBAction func buttonPressed(sender: AnyObject) {
performSegueWithIdentifier(segueProfileToPul, sender: sender)
}
Connect all buttons to the buttonPressed(). I don't think this line let numberOfCameras = destinationController.Camera.countworks since the SelectionTableViewController is not instantiated yet and thus has no values in its variables (I think). What you are looking for are probably setting this value so destinationController.Camera.count = someValue. Maybe I'm wrong though.
Edit
I uploaded a test project showing what I mean. Pay attention to the connections I've made in storyboard. Download here

Related

how to dismiss current view controller while segue time in swift3

This is my segue method. Let's say this method is in ParentViewController.
override fu n c prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "subViewController" {
// Before appears in the screen.
let subViewController = segue.destination as! SubViewController
subViewController.currentMarks = sender as? Int16
}
It is working perfect. Now coming to SubViewController. Here I'm doing some thing and I have a button here. Whenever I click this button it should dismiss SubViewController and needs to open ParentViewController (not opening because it's already opened state only).
Exactly whenever I click button in SubViewController, subViewController just needs to dismiss then automatically ParentViewController will be visible I think (because already opened one only I'm not closed right?).
How to implement like this mechanism? In SubViewController button action I have written this:
self.navigationController?.dismiss(animated: true, completion: {
})
but it didn't work. Can anybody help me please?
If you chose show when you created your segue on stoyboard. Call this in your button click:
self.navigationController?.popViewController(animated: true)
If you chose present modally call this:
self.dismiss(animated: true, completion: nil)

trying to go to next screen after user taps on cell in table

In a previous post, the below code was given as an answer to the question i have. When i tried using that code and replacing with my variables, etc I am getting an error.
'selectedValue' - error is "value of type ViewController has no member 'selectedValue'"
what does selectedValue represent?
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "Details" {
let destination = segue.destinationViewController as? SecondViewController
let cell = sender as UITableViewCell
let selectedRow = tableView.indexPathForCell(cell)!.row
destination!.selectedValue = items[selectedRow]
}
}
This code looks like the code you'd use to pass the selected data from one view controller to another when a cell is selected, am I right?
In your code, selectedValue should be a variable declared in SecondViewController. It is where you're passing the data to.

didSelectRowAtIndexPath and performSegueWithIdentifier

I have a tableView that display a list of cells. I need to catch the selected cell, and pass my object data based on indexPath.row to display it on my Second View Controller. My didSelectRowAtIndexPath is working fine, but probably I'm not familiar with the syntax for performSegueWithIdentifier, where it fails to call the method.
Sorry I'm new to Swift programming, would appreciate if you could explain more details.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
selectedCell = indexPath.row
performSegueWithIdentifier("DetailScreen", sender: self)
}
override func performSegueWithIdentifier(identifier: String, sender: AnyObject?) {
detailedView.personName = personList[selectedCell].GetPersonName()
}
Solution 1
First, make sure you have segue between your first and second view controllers (From the table view controller one to the Detail view screen). Make sure that the segue has a name
Now in your first view controller's didSelectRowAtIndexPath event, Invoke the segue like this.
performSegueWithIdentifier("DetailScreen", sender: nil)
Now in the prepareForSegue method of the first view controller, you can customize it to send more details.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if(segue.identifier=="DetailScreen")
{
let ctrl = segue.destinationViewController as! YourDetailsViewController
ctrl.personName = "Set some person name here"
}
}
Assuming Your Detail screen's class is called YourDetailsViewController and it has a property called personName of String type. You may update the code to use your real view controller.
Solution 2
If you do not want to create the segue, you can programmatically navigate( actually pushing the second view controller to the front) to the second view. In your first view controllers, didSelectIndexPathAtRow method,
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
let ctrl = self.storyboard?.instantiateViewControllerWithIdentifier("DetailsCtrl")
as? YourDetailsViewController
ctrl?.personName="Set some name here"
self.navigationController?.pushViewController(ctrl!, animated: true)
}
For the above code to work, you need to make sure that you have StoryBoardID set to "DetailsCtrl" on the second view controller(Details view)
You have set the storyboard segue as given below:
Click on the segue and add the identifier
You can achieve the above requirement using the following code and this worked for me:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
let storyboard1 = UIStoryboard(name: "Main", bundle: nil)
let detail = storyboard1.instantiateViewControllerWithIdentifier("DetailScreen") as! SecondViewController
detail.personName = personList[selectedCell].GetPersonName()
self.navigationController?.pushViewController(detail, animated: true)
}
The storyboard segue from your first view controller to second view controller should be "Push".
Hope this might be helpful.

Could not cast value of type 'UINavigationController'

I am implementing a search interface for my application, so basically I will pass the search keyword from one ViewController to another ViewController.
I have done this type of parameter passing several times but something seems strange this time. The destination ViewController is embedded in a Navigation Controller.
Now the code looks something like this.
override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject!) {
if (segue?.identifier == "home_to_search") {
var searchKeyword = txtSearchBarHome.text
var svc = segue?.destinationViewController as! SearchViewController;
svc.toPassSearchKeyword = searchKeyword;
//let nav = segue?.destinationViewController as! UINavigationController
//let svc = nav.topViewController as! SearchViewController
//svc.toPassSearchKeyword = searchKeyword;
}
}
I have already explored these questions
DestinationViewController Segue and UINavigationController swift, How do I segue values when my ViewController is embedded in an UINavigationController? with no luck.
What makes me wonder is that I already have ViewControllers embedded in Navigation Controllers that I can pass parameters by segueing. However, in this case it throws a Could not cast value of type 'UINavigationController' error. If I try the commented code above it does not throw an error there, but at the AppDelegate class.
Answering my own question. In this case we need to access the child view by doing something like this:
let nav = segue?.destinationViewController as! UINavigationController
let svc = nav.topViewController as! SearchViewController
svc.toPassSearchKeyword = searchKeyword;
Based on Semih's answer, you can also do this to pass a variable to next segue if you don't want to use an identifier:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let nav = segue.destination as? UINavigationController,
let vc = nav.topViewController as? TestViewController {
vc.username = "Test"
}
}
Just a quick note for those looking into this issue it has been renamed to Destination
let nav = segue.destination as! UINavigationController
let svc = nav.topViewController as! SearchViewController
svc.toPassSearchKeyword = searchKeyword;

Trigger Segue Artificially

I am trying to pass data between two viewContollers in an OS X storyboard application using Swift. When I press a button on VC1, it opens VC2, and prepareForSegue is run. However, I can't pass data back to VC1 because a. prepareForSegue isn't being run (because a window isn't being opened) and b. because even if it were, VC1 doesn't know data is being sent and I can't figure out a function (something like viewDidBecomeFocus, if such a function existed) to let it know to look. I feel like there must be a way to do this.
If you know of a way to do this in IOS but not OSX, it could still be useful.
Thanks!
Let assume that in your first ViewController you have one label and one button. When pressed, that button open popover (SecondViewController) with one textfield (and one button what says ready or close etc.), where you want take its value and assign it to your label. That is where delegates and protocols come handy.
SecondViewController:
#objc protocol TextDelegate {
func passedString(textValue: String)
}
class SecondViewController: NSViewController {
#IBOutlet weak var textField: NSTextField!
weak var delegate: TextDelegate?
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
}
#IBAction func closePopOver(sender: AnyObject) {
if delegate != nil {
delegate!.passedString(textField.stringValue)
}
self.dismissViewController(self)
}
}
This is ViewController:
#IBOutlet weak var myLabel: NSTextField!
override func prepareForSegue(segue: NSStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "mySegue" {
let vc = segue.destinationController as! SecondViewController
vc.delegate = self
}
}
func passedString(textValue: String) {
myLabel.stringValue = textValue
}

Resources