Missing back button in my ViewController after seque from TableViewControler in Swift - ios

In my project, I have a few View Controllers and I use UINavigationController.
When I make a seque from UIViewController to UITableViewController I have "back" button added automatically, but when I make seque from UITableViewController to UIContentViewController tapped a cell, I don't have a "back" button in UIContentViewController.
Plan of my app is here
The segue in UITableViewController looks like that:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let CV = self.storyboard?.instantiateViewControllerWithIdentifier("ContentViewController") as! ContentViewController
let tnumber = tableView.indexPathForSelectedRow?.item
CV.titleContent = daneOWpisach?[tnumber!]["title"]
CV.webContent = daneOWpisach?[tnumber!]["description"]
CV.category = category
self.presentViewController(CV, animated: true, completion: nil)
}
What should I do, if I would like to have a back button in UIContentViewController added automatically?

In your code you are presenting the view controller on cell selection..! Back button will show only if you perform push not on presenting the view.
In the above diagram what I have seen is you already make the segue from UITableViewController to UIContentViewController. select the segue and go to attribute inspector give the identifier for the segue.
On the cell selection perform the segue action with the identifier you specified
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("Your Segue name", sender: sender)
}
If you want to pass data to destination view controller, do it like below..
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
if segue.identifier == "Your Segue name" {
let CV = segue.destinationViewController as! ContentViewController
let tnumber = tableView.indexPathForSelectedRow?.item
CV.titleContent = daneOWpisach?[tnumber!]["title"]
CV.webContent = daneOWpisach?[tnumber!]["description"]
CV.category = category
}
}
Hope this helps you

Related

Segue To View Controller Inside Of A UITableView

How do you segue from a ViewController to a ViewController located in a UITableView (which is in a NavigationController)?
Image of Storyboard with description
I can Control-Drag from my "DetailButton" to the "DetailViewController", but it is not displayed in the navigation controller if you do that. The NavigationBar should still allow a user to go back to the UITableView, even if they segued here from the "DetailButton".
Here's the solution I came up with. If anyone else has a better way, please post it here.
Storyboard Steps:
Control-Drag from the "DetailButton" to the Navigation Controller to create a segue. Give this segue the identifier "detailSegue".
Control-Drag from the UITableViewCell you would like to link to DetailViewController to the DetailViewController. Give this segue the name "showDetail".
UITableViewController Steps:
var shouldSegueToDetail = false
override func viewDidLoad() {
...
// Check if we should segue to DetailViewController
if shouldSegueToDetail {
// Reset flag
shouldSegueToDetail = false
// Go to DetailViewController
performSegue(withIdentifier: "showDetail", sender: self)
}
}
OriginalViewController Steps:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "detailSegue" {
let navigationVC = segue.destination as! UINavigationController
let tableVC = navigationVC.viewControllers[0] as! UITableViewController
tableVC.shouldSegueToDetail = true
}
}
Option:
Instead of making a segue from the UITableViewCell to the DetailViewController, you could probably call UITableView's selectRow method with the IndexPath of the item you want selected.

Xcode: Passing Information from UITableViewController to UIViewController

I have a UIViewController which should show me DetailInformations depending on what Cell was pressed in the UITableViewController.
For the moment I am passing them through a sequel:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "show" {
var ctrl = segue.destination as! DetailViewController
ctrl.information = _informationList[id]
}
}
The id variable is set through:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
id = indexPath.row
}
Now in my UIViewController I change the information with:
override func viewDidLoad() {
super.viewDidLoad()
setInformation(i: information)
}
Now my problem is, that if I press, lets say cell 2. It switches to the ViewController and shows Information of cell 1. Than I go back to the tableview and I press cell 3. Then it shows me cell 2.
In short, it seems that the viewController is loaded (with the last information), before it sets the new information.
Is there any better way to solve this?
Try using indexPathForSelectedRow in prepareForSegue as of it looks like that you have created segue from UITableViewCell to the Destination ViewController so that prepareForSegue will call before the didSelectRowAt.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "show" {
var ctrl = segue.destination as! DetailViewController
if let indexPath = self.tableView.indexPathForSelectedRow {
ctrl.information = _informationList[indexPath.row]
}
}
}
I am assuming based on what you are describing is that you used a segue in your Storyboard to link directly from the cell to the detail view controller. This is not what you want to do, as mentioned earlier, because you don't get the order of events you would expect. You could use the delegation design pattern for this, but assuming you want to stick with segues you need to make the "show" segue from the table VC itself to the detail VC. You then manually call the segue from the tableView didSelectRowAt code.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
id = indexPath.row
performSegue(withIdentifier: "show", sender: self)
}
Finally, you could then use an unwind segue when you come back to catch any data changes initiated in the detail VC.

Passing Data Between Controllers in Swift

I want to passing data between TableViewController and ViewController
the program does not go into the method
My swift code:
override func unwind(for unwindSegue: UIStoryboardSegue, towardsViewController subsequentVC: UIViewController) {
let destView : ViewController = unwindSegue.destination as! ViewController
destView.min = Int(minTable)
destView.tableText = unitsText
}
I take data:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let tableCell = moneyArray[indexPath.row]
minTable = tableCell.val
unitsText = tableCell.name
let _ = navigationController?.popViewController(animated: true)
}
Adn my Table Code:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "LabelCell", for: indexPath) as! TableViewCell
let tableShow = moneyArray[indexPath.row]
cell.nameCurrency?.text = tableShow.name
cell.valueCarrency?.text = "\(tableShow.val)"
return cell
}
You are using popViewController on your didSelectRow, that means that you are returning on your navigation controller and not pushing a unwind segue or any segue, so you cant use prepareForSegue/unwind method.
One correct way of solving this is using delegation.
You can find more information about that here:
Passing data back from view controllers Xcode
But if you want to use unwind segue, you will have to write your unwind method on the previous viewController, not your current. Also you will need to use the method performSegue with the identifier of your unwind segue.
You can see more information about unwind segues here:
What are Unwind segues for and how do you use them?
If you want to open a detail view controller when the user clicks on a cell in your main table view controller then the proper way to pass data is by using something like the following:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "MyDetailView") {
// pass data to next view
if let viewController: MyDetailsViewController = segue.destinationViewController as? MyDetailsViewController {
viewController.units = mySelectedTableCell.unitsName
}
}
}
Full docs here.

pushViewController does no action

i have a tableview and i want to go to another vc when one of rows tapped. my didSelectRowAtIndexPath function is as below. print command works and shows the right clicked row. but when i use self.navigationController?.pushViewController it does not go to vc with playVideo storyBoardId. after changing it to presentViewController it works. what's wrong about my code that push doesn't work?
thanks
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("clicked " + String(indexPath.row) )
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("playVideo") as! PlayVideoViewController
vc.id = self.video[indexPath.row].id
// Present View as Modal
//presentViewController(vc as UIViewController, animated: true, completion: nil)
// Push View
//self.navigationController?.pushViewController(vc, animated: true)
}
Its because the view controller you are currently in may not have a navigation controller.
You cannot push a view controller without having a UINavigationController.
If your requirement is to push a view controller, then perform the following steps.
Embed a navigation controller for the current view controller.(Open storyboard -> Choose your view controller -> Choose "Editor" -> "Embed in" -> UINavigationController)
Now your code
self.navigationController?.pushViewController(vc, animated: true)
will be working fine.
Make sure that your ViewController is indeed built on a NavigationController. Try forcing the line:
self.navigationController!.pushViewController
if it crashes, you know there is not nav set up. Or you could just check in your storyboard but this is a quick way to tell.
I dont know why are you doing it like this. I think its unnecessarily complicated.
This should by your function didSelectRowAtIndexPath:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("playVideo", sender: tableView)
}
Then you can specify as much segues as you want in this function:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "playVideo") {
let indexPath:NSIndexPath = tableView.indexPathForSelectedRow!
let PlayVideoViewController = segue.destinationViewController as! PlayVideoViewController
//you can pass parameters like project id
detailVC.projectID = ids[indexPath.row]
}
}
Your segue has to be named like this in interface builder:

segue from UIViewController to UITableViewController

I'm trying to segue data from UIViewController to UITableViewController.
The data in UIViewController is coming from PFTableViewController and I want to pass that data to another TableViewController.
For passing to ViewController didSelect method is used but I have no idea how can I segue from viewController to TableViewController.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let destinationToFVC:ViewController = self.storyboard!.instantiateViewControllerWithIdentifier("FVCont") as! ViewController
if let indexPath = self.tableView.indexPathForSelectedRow {
let row1 = Int(indexPath.row)
destinationToFVC.currentObject = objects?[row1] as! PFObject!
}
navigationController?.pushViewController(destinationToFVC, animated: true)
}
I'm new to programming.
In your case you can launch the segue manually from your didSelectRowAtIndexPath, with the the method performSegueWithIdentifier.
You need to create a custom segue in your Storyboard from your UIViewController to your UITableViewController and set an Identifier for it, you can press Ctrl + Click from your UIViewController to the next to create the custom segue and then select the segue and in the Attributes Inspector set the Identifier for the segue just a this picture:
Then you can in your didSelectRowAtIndexPath launch the segue manually as in this code:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// the identifier of the segue is the same you set in the Attributes Inspector
self.performSegueWithIdentifier("mySegueID", sender: self)
}
And of course you need to implement the method prepareForSegue to pass the data from your UIViewController to your UITableView like in this code:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "mySegueID") {
// in this line you need to set the name of the class of your `UITableViewController`
let viewController = segue.destinationViewController as UITableViewController
let indexPath = self.tableView.indexPathForSelectedRow()
destinationToFVC.currentObject = objects?[indexPath] as! PFObject!
}
}
EDIT:
If you want to perform your segue from an UIButton to the UITableViewController it's the same logic, just create the custom segue in your Storyboard and then call the prepareForSegue like in the following code:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "mySegueID") {
// in this line you need to set the name of the class of your `UITableViewController`
let viewController = segue.destinationViewController as UITableViewController
/ here you need to pass the data using the reference viewController
}
}
I hope this help you.

Resources