I created a table view where the user is able to add rows by clicking an "add" button in navigation bar. When the user selects a row the app shows another table view. I want to set the title of the navigation bar to the name of the selected row.
I know how to set the title of the navigation bar if I pass the name to label in the second table view.
title = self.restaurant.name
But I haven't figured out how to pass it to the navigation bar without creating a extra label.
It's actually really easy. All you have to do is implement prepareForSegue and use sender to create an instance of UITableViewCell. From there you can easily get the title of that cell and using segue.destinationViewController you can set the nav bar title of the subsequent view controller.
import Foundation
import UIKit
class TableViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CellID", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = "Cell at row \(indexPath.row)"
return cell
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let destinationVC = segue.destinationViewController as UIViewController
let cell = sender as UITableViewCell
destinationVC.navigationItem.title = cell.textLabel?.text
}
}
Related
I am relatively new to Swift/Xcode and I am trying to make a view controller appear with different values when a button is selected (an add button) or a table view cell is selected (which allows them to edit). However, I am unable to get any response upon the selection of my row including a print statement I have put in for testing, although the segue does function when I link the transition to a button. The code is identical to that of a functioning table view cell I wrote previously that makes the current table view appear. Could this be an issue with the storyboard?
Storyboard screenshot with cell settings
Here is my code:
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath)
cell.textLabel?.text = items[indexPath.row].name
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("Selected")
}
//Sends current receipt information to the AddItemViewController display when tapped
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "AddItemViewSegue" || segue.identifier == "EditItemViewSegue" {
let destination = segue.destination as? AddItemViewController
destination?.currentReceipt = currentReceipt
let index = tableView.indexPathForSelectedRow?.row
print("test")
if segue.identifier == "AddItemViewSegue" {
destination?.addMessage = "Add a New Item to Your Receipt"
destination?.buttonMessage = "Add Item"
}
else {
print("test1")
destination?.addMessage = "Edit an Item in Your Receipt"
destination?.buttonMessage = "Edit Item"
destination?.currentItem = items[index!]
}
}
}
I have also looked into this forum post because it is similar to mine but I was unable to apply any of the suggested fixes.
https://developer.apple.com/forums/thread/14842
First of all the didSelectRow method is wrong. The code is Swift 2 code. The proper signature is
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { ...
Didn't you wonder why the compiler doesn't complain about the missing override?
Rather than from the view controller reconnect the segue (why are there 2 ones?) from the table view cell to the destination controller and delete didSelectRow
This question seems to have been asked many times on StackOverflow, but after searching for hours, I still haven't found the solution to my issue.
I have a table view in SecondViewController.swift and I did make it delegate and dataSource SecondViewController.swift, but the didSelectRowAt method is still not fired when a table cell is clicked. I am trying to apply a segue to another view controller, but the didSelectRowAt method isn't working itself.
I have selected Single Selection in my storyboard in the table view properties, and I have made sure that user interaction is enabled for the table view and the prototype cell.
For the SecondViewController.swift below, please assume that allEvents are populated into the allEvents array. I was able to successfully populate them and display them in the table. The only problem is clicking on the row to perform a segue. Also, please ignore the awkward indentation below.
SecondViewController.swift
import UIKit
class SecondViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableView: UITableView!
var allEvents: Array<JSON> = []
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
//self.tabBarItem.image = myTabImage
self.tabBarController?.tabBar.isTranslucent = false
self.tabBarController?.tabBar.barTintColor = UIColor(red:0.25, green:0.25, blue:0.25, alpha:1.0)
self.tabBarController?.tabBar.tintColor = UIColor.white
//ASSUME ALL EVENTS ARE POPULATED INTO allEvents
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: Tableview Datasource
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return allEvents.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 150
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("SEGUE")
self.performSegue(withIdentifier: "oneSegue", sender: allEvents[indexPath.row])
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "eventViewTableCell", for: indexPath) as! EventViewTableCell
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// let detailController = segue.destination as! EventDetailsController
}
}
I have been on this for hours and still have not found out the problem. I would greatly appreciate any help!
You may want to check your tableview again, do choose single selection.
I'm assuming you are selecting No Selection as the picture bellow
Hope it helps.
I had the same problem on a Controller within a TabBarController.
What fixed it for me was this:
Disable the User Interaction for the Content view
My guess is that it was becoming the responder so it removed the event from the TableView
Note: Since the viewDidLoad assignments to delegate and dataSource became redundant after setting it up in the StoryBoard, I removed them, although leaving them does no harm.
If you do nothing else than calling the segue in didSelectRowAt remove the entire method and connect the segue in Interface Builder to the table view cell (rather than to the controller). The sender parameter will contain the reference to the selected table view cell.
I suspect when you collected and populated your allEvents array did you collect any touch events in there ?
or have you used UIGestureRecognizer in this or it's super view ?
If you have intercepted any touch event to populate your array or any other purpose comment it out and test it with a simple preloaded array like :
let dataSource = ["1", "2", "3", "4"]
let me know if this is not your case so I can find another solution.
I have a spit view. The master is a table view. I want to put a fixed label above the table view (like a fixed header). How can I do that in the storyboard ?
In Table View Controller can't add a fixed part. But you can use a View Controller and table view in it. With this solution you can set a fixed pat at Top,Bottom or on table view.
First add a view controller to storyboard
add tableview to view controller
In inspector, table view > set prototype Cell = 1
In inspector, table view cell > set Identifier = cell
Add a viewcontroller.swift and write this code on it look like below
import UIKit
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var arrayTest : [String] = []
override func viewDidLoad() {
super.viewDidLoad()
arrayTest = ["iPad","iPhone","iPod","macOS","iOS"]
tableView.delegate = self
tableView.dataSource = self
tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayTest.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = arrayTest[indexPath.row]
return cell
}
}
In this step your table is set to view controller and you can add view in top of the table view and add label on view.
Now you have a fixed header on top of table view.
You can see picture of all steps in this picture. Enjoy it.
All image of toturial
This is my first time using TableView's and I've already hit a road block.
I've got a View Controller with a Container inside. The Container View has an embedded Table View Controller. I have populated the table view controller using the below code. I have set the datasource and the delegate to the Table View Controller, set the Custom Class of the Table View controller to ORMTableVC and set the Table View cell Identifier to cellIdentifier.
My problem is at runtime the View Controller is just blank and I cannot see any Table lines or data.
Any help will be greatly appreciated.
import Foundation
import UIKit
class ORMTableVC : UITableViewController {
let cellIdentifier = "cellIdentifier"
var Array = [String]()
override func viewDidLoad() {
super.viewDidLoad()
Array = ["Reps", "Weight", "RPE", "Fatigue", "Potential Max", "Fatigue Weight"]
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Array.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let Cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)
Cell.textLabel?.text = Array[indexPath.row]
return Cell
}
}
StoryBoard Setup
Built App
After looking through many tutorials managed to fix this. Seemed like the code wasn't the issue it was the storyboard setup.
On the Table View Cell the identifier needed to be cellIdentifier not Cell.
Another noob question but I could really do with some help on this one. I am looking for a way to have a list of cells in a dynamic prototype table view and each cell to go to a new view controller. I have managed to do this to about 75% :/. Basically I have made it work but it always loads the first cell first because its reuse identifier is called cell. Is there a way to make each one just load the View Controller I want? (code below)
Thanks
Sam
Edit 1: I have changed code to how it now looks below. But the Alton Barnes view controller is still loading in front of which ever cell you click and want to see.
import UIKit
class LocalAttractionsTableViewController: UITableViewController {
#IBOutlet weak var menuButton: UIBarButtonItem!
var Locations = ["Alton Barnes White Horse","Avebury","Barbury Castle","Bowood","Broad Town White Horse","Caen Locks","Cherhill White Horse","Corsham Court","Devices white Horse","Dragon Hill","Hackpen Hill White Horse","Iford Manor","Lacock","Longleat House","Longleat Safari Park","Marlborough white Horse","Pewsey White Horse","Salisbury Cathedral","Sheldon Manor","Silbury Hill","Stonehenge","The Barge Inn","Uffington White Horse","Westbury White Horse","West Kennet Long Barow","Wilton Windmill","Woodhenge"]
override func viewDidLoad() {
super.viewDidLoad()
// Side Menu
if self.revealViewController() != nil {
menuButton.target = self.revealViewController()
menuButton.action = "revealToggle:"
self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
}
tableView.backgroundColor = UIColor.grayColor()
tableView.tableFooterView = UIView(frame:CGRectZero)
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 27
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Locations.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel!.text = Locations[indexPath.row]
cell.backgroundColor = UIColor.clearColor()
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{performSegueWithIdentifier(Locations[indexPath.row], sender:self);
}
}
I guess you have created the segues the wrong way.
If you have ctrl-dragged a segue from the prototype cell in InterfaceBuilder, this segue is performed without code. Then in your code you call performSegueWithIdentifier(...) which causes another segue to trigger.
You need to ctrl-drag all the segues from the tableViewController icon in InterfaceBuilder to the destination viewControllers and then give them the identifiers.
you created a segue with identifier name : Alton . Instead of "Alton" you need to rename the Segue identifier as Alton Barnes White Horse , later you need to do :
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {performSegueWithIdentifier(Locations[indexPath.row], sender:self);