I'm experiencing what I'm sure is a beginner's mistake. I have a TableViewController that should segue to a second TableViewController upon selection of a custom cell.
I've segued to a UIViewController from a custom cell in the past but I can't figure out for the life of me why this segue isn't firing. Here's the code for the entire controller that should be firing the segue. Thanks in advance!
import UIKit
class SourcesViewController: UITableViewController {
var sources: [Source] = []
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.isNavigationBarHidden = false
self.navigationItem .setHidesBackButton(true, animated: false)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sources.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell_01", for: indexPath) as? SourceCell
else {
return tableView.dequeueReusableCell(withIdentifier: "cell_01", for: indexPath)
}
let currentSource = sources[indexPath.row]
cell.sourceLabel.text = currentSource.name
return cell
}
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let indexPath = tableView.indexPathForSelectedRow {
let sourceToSend = sources[indexPath.row]
if let destination = segue.destination as? ArticlesViewController {
destination.source = sourceToSend
}
}
}
}
Your segue doesn't get called because you are not invoking it. UIViewController has perfromSegue method that you should use for that purpose.
From what I see you would want to perform the segue after tapping the cell. To achieve this add UITableViewDelegate method and perform segue from there:
/// - SeeAlso: UITableViewDelegate
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "your_identifier_from_the_storyboard", sender: nil)
}
Related
I have already shown a list of metro station on the screen, what I want to do is when clicking different stations, they can pass their information to the second tableview and display, how to do that by using segue and didselectRowAt?
tablecell class
class LandmarksTableViewCell: UITableViewCell {
#IBOutlet weak var LandmardsImage: UIImageView!
#IBOutlet weak var LandmarksLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
metrostationViewController
class MetroStationsViewController: UITableViewController{
let wmataapimanager = WmataAPIManager()
let locationDetector = LocationDetector()
var stations = [Station](){
didSet{
tableView.reloadData()
}
}
var landmarks = [Landmark]()
override func viewDidLoad(){
super.viewDidLoad()
wmataapimanager.delegate = self as FetchStationsDelegate
locationDetector.delegate = self as LocationDetectorDelegate
fetchStation()
}
private func fetchStation(){
locationDetector.findLocation()
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 120
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return stations.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "StationCell", for: indexPath) as! StationsTableViewCell
let station = stations[indexPath.row]
cell.StationLabel.text = station.name
//cell.LaiLabel.text = String(station.Lat)
//cell.LonLabel.text = String(station.Lon)
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("you select: \(indexPath.row)")
let selectStation = stations[indexPath.row]
let currentCell = tableView.cellForRow(at: indexPath)! as UITableViewCell
}
}
In didSelectRowAt delegate method perform segue and as sender pass selected station
performSegue(withIdentifier: "identifier", sender: stations[indexPath.row])
then you should have variable in destination ViewController and you can assign this variable in prepare for segue method as downcasted sender
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "identifier" {
let destinationVC = segue.destination as! DestinationViewController
destinationVC.station = sender as! Station
}
}
I can't get a simple segue to work when a cell in a tableview gets pressed. It does go to the next view after I tapped two different items. But I can't pass any values from the first controller to the second. If I set a value to the label in the second controller and load it in the viewDidLoad method it shows up.
I'm going crazy as I've been trying to get this work for ages....
My storyboard: https://snag.gy/DCw9MU.jpg
CategoryListViewController(1st controller):
import Foundation
import UIKit
class CategoryListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var categoryList = TestData.sharedInstance.categoryList
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = "iEngineer"
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
self.tableView .reloadData()
tableView.dataSource = self
for category in categoryList{
print(category)
}
}
// MARK: - Segues
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showFormulaList" {
if let indexPath = tableView.indexPathForSelectedRow {
let category = self.categoryList[indexPath.row]
let formulaListViewController = (segue.destination as! UINavigationController).topViewController as! FormulaListViewController
formulaListViewController.text = category
formulaListViewController.navigationItem.leftBarButtonItem = splitViewController?.displayModeButtonItem
formulaListViewController.navigationItem.leftItemsSupplementBackButton = true
}
}
}
// MARK: - Table View
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(categoryList.count)
return categoryList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "categoryCell", for: indexPath)
let object = categoryList[indexPath.row]
cell.textLabel!.text = object
return cell
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showFormulaList", sender: self)
}
}
FormulaListViewController(2nd controller):
import Foundation
import UIKit
class FormulaListViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var titleLabel: UILabel!
var formulaList = TestData.sharedInstance.formulaList
var fSwift: String!
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = "iEngineer"
print(fSwift)
titleLabel.text = fSwift
}
// MARK: - Table View
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(formulaList.count)
return formulaList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "formulaCell", for: indexPath)
let object = formulaList[indexPath.row]
print(object)
cell.textLabel!.text = object
return cell
}
}
Where is my mistake or what am I doing wrong?
I greatly appreciate any help
You need didSelectRowAt instead of didDeselectRowAt
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showFormulaList", sender: self)
}
Also make sure segue source is the vc not the cell , and since you fire the segue in didDeselectRowAt this
if let indexPath = tableView.indexPathForSelectedRow
will be nil
You have used didDeselectRowAt:
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showFormulaList", sender: self)
}
You need to use didSelectRowAt:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showFormulaList", sender: self)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showFormulaList", sender: self)
}
You should use didSelect instead of didDeselectRowAt, also you should pass something better than self, because with self you are passing the entire CategoryListViewController
Try to pass the indexPath like this
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "showFormulaList", sender: indexPath)
}
and change the function prepare in this
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showFormulaList" {
if let indexPath = sender as? IndexPath {
let category = self.categoryList[indexPath.row]
let formulaListViewController = (segue.destination as! UINavigationController).topViewController as! FormulaListViewController
formulaListViewController.fuckSwift = category
formulaListViewController.navigationItem.leftBarButtonItem = splitViewController?.displayModeButtonItem
formulaListViewController.navigationItem.leftItemsSupplementBackButton = true
}
}
}
If this doesn't help you try to debug your code and find where you lost your variable :)
I'm trying to change the title of the new navigation bar to match the tableview cell that was pressed, moving the user to the next viewcontroller.
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
folderCellSelected = folderNames[indexPath.row]
}
Grabs the name of the cell that was selected
override func viewDidLoad() {
super.viewDidLoad()
self.title = FoldersViewController.folderCellSelected
// Do any additional setup after loading the view.
mindmapNames.append("Task")
mindmapNames.append("Other Task")
}
And is supposed to insert the name of the cell, changing the title of the new page
But i can't figure out what to write instead of FoldersViewController.folderCellSelected
Instance member 'folderCellSelected' cannot be used on type 'FoldersViewController'
is the error i get
You can use the function override func prepare(for segue: UIStoryboardSegue, sender: Any?)
to send a value to the next view controller like that :
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var mytbl: UITableView!
var foldernames = ["test","test1"]
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "next"{
let nextViewController = segue.destination as! NextViewController
nextViewController.myTitle = foldernames[sender as! Int]
}
}
}
extension ViewController : UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return foldernames.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = foldernames[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "next", sender: indexPath.row)
}
}
myTitle is a variable from NextViewController
and then in the NextViewController do this :
class NextViewController: UIViewController {
var myTitle = ""
override func viewDidLoad() {
super.viewDidLoad()
self.navigationItem.title = myTitle
}
This question already has answers here:
Send data from TableView to DetailView Swift
(4 answers)
Closed 5 years ago.
I'm trying to recognize which tableviewcell is selected and after that i want to get the label value of that cell and pass it to the next view controller. My cell has a Label value which is string and a Number value which is Int. I'm using a firebase database to get all that data.
My code:
import UIKit
class PlacesTableViewController: UITableViewController {
//MARK: Properties
#IBOutlet weak var placesTableView: UITableView!
var places = [Places]()
override func viewDidLoad()
{
super.viewDidLoad()
// Loads data to cell.
loadData()
}
override func numberOfSections(in tableView: UITableView) -> Int
{
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
//return the number of rows
return places.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
// Table view cells are reused and should be dequeued using a cell identifier.
let cellIdentifier = "PlacesTableViewCell"
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? PlacesTableViewCell else {
fatalError("The dequeued cell is not an instance of PlacesTableView Cell.")
}
let place = places[indexPath.row]
cell.placeLabel.text = place.name
cell.ratingControl.rating = place.rating
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
print(places[indexPath.section])
self.performSegue(withIdentifier: "ShowCommentsTableViewController", sender: nil)
}
}
you can follow this thread to be useful send-data-from-tableview-to-detailview-swift
You have to create variable in destination view controller and store data in those Variable before Moving to Destination View controller.
This link will help you for this.
Try this:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
let selectedPlace = places[indexPath.section]
self.performSegue(withIdentifier: "ShowCommentsTableViewController", sender: selectedPlace)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let selectedPlace = sender as? Places,
let destViewController = segue.destination as? SecondViewController {
destViewController.place = selectedPlace
}
}
I'm new to Swift and working on a small project.
I have two UITableViewController: TableViewController and DetailViewController.
Click on TableViewController cell will navigate to DetailViewController.
Click on DetailViewController cell will navigate back to TableViewController and update the detailTextLabel?.text with selected item.
The problem right now is I don't know how to update the detailTextLabel?.text.
I can pass the selected data from DetailViewController to TableViewController but not sure how to update the cell.
class TableViewController: UITableViewController,DataSelectedDelegate{
var sessions=[Session]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.sessions = [Session(Game: "Game", Detail: "SuperTrack"),Session(Game: "Type",Detail : "Race")]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func userSelectedInformatiom(info:NSString){
//cell.detailTextLabel?.text=info
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.sessions.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
var session:Session
session=sessions[indexPath.row]
cell.textLabel?.text = session.Game
cell.detailTextLabel?.text = sessions[indexPath.row].Detail
return cell
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDetail"{
let detailVC:DetailViewController = segue.destinationViewController as DetailViewController
detailVC.delegate=self
}
}
}
DetailViewController:
import UIKit
protocol DataSelectedDelegate{
func userSelectedInformatiom(info:NSString)
}
class DetailViewController: UITableViewController {
var types=[GameType]()
var test:String!
var delegate:DataSelectedDelegate? = nil
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.types = [GameType(Type:"Race"),GameType(Type:"Shoot"),GameType(Type:"Kid"),GameType(Type:"Adult")]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return types.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//let identifier: String = "tableCell"
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cells", forIndexPath: indexPath) as UITableViewCell
var type:GameType
type=types[indexPath.row]
cell.textLabel?.text = type.Type
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//println("You selected cell #\(indexPath.row)!")
//let selectedCell = tableView.cellForRowAtIndexPath(indexPath)
//selectedCell?.accessoryType = .Checkmark
if (delegate != nil){
let selectedIndex:NSString=types[indexPath.row].Type
delegate!.userSelectedInformatiom(selectedIndex)
self.navigationController?.popViewControllerAnimated(true)
}
}
}
There are multiple possible solutions:
You can pass the selected cell to the detailViewController in prepareForSegue (the sender object is the tapped cell). Then you can pass that information back in your delegate call.
You can examine the indexPath of the selected row in the delegate function userSelectedInformatiom via self.tableView.indexPathForSelectedRow(). With that indexPath you get the cell via cellForRowAtIndexPath.
You can store a reference to the selected cell before the segue is performed
...