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
}
}
Related
I'v tried to get array from UITableViewController to another ViewController. I have navigationController and main screen is MyTableViewController. I'm trying to pass data with Segue. Here is the part of MyTableViewController. All other code in this file are correct.
MyTableViewController
struct Faculty {
var name = String()
var descriptions = [String]()
}
let faculties = [
Faculty(name: "Faculty of Architecture", descriptions: ["Architecture and Urban Planning", "Spatial Planning"]),
Faculty(name: "Faculty of Civil Engineering", descriptions: ["Civil Engineering"]),
Faculty(name: "Faculty of Chemistry", descriptions: ["Biotechnology", "Chemistry","Chemical and Process Engineering", "Materials Science and Engineering", "Chemical Technology"]),
Faculty(name: "Faculty of Electronics", descriptions: ["Control Engineering and Robotics", "Electronics", "Telecommunications", "Teleinformatics", "Technical Computer Science"])]
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath)
tableView.deselectRow(at: indexPath, animated: true)
performSegue(withIdentifier: "showDetail", sender: cell)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail",
let indexPath = self.tableView.indexPathForSelectedRow {
let sendDescriptions = faculties[indexPath.row].descriptions
let destination = segue.destination as? ViewController
destination?.getDescriptions = sendDescriptions
}
}
ViewController
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tableView: UITableView!
var getDescriptions = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
print(getDescriptions)
tableView.delegate = self
tableView.dataSource = self
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return getDescriptions.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "detailIdentifier", for: indexPath)
let row = indexPath.row
cell.textLabel?.text = getDescriptions[row]
return cell
}
I'm having difficulty with passing a realm object's data from a tableViewController to a viewController. I want to choose one of the objects from the table and have that object's data be used in the following viewController. I've struggled to find resources here which deal with Realm objects instead of just passing strings and the likes. Any assistance would be great.
Here's my TableViewController with my attempt at creating a segue function to the second view :
class WorkoutController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return DBHelper.shared.getWorkout().count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
}
let muscle = DBHelper.shared.getWorkout()[indexPath.row]
cell.textLabel?.text = muscle
return cell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let workoutDetailVC = segue.destination as! WorkoutDetail
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let name = DBHelper.shared.getWorkout()[indexPath.row]
workoutDetailVC.receivedName = name
}
}
}
Here's the WorkoutDetail class which is supposed to receive and show the data :
class WorkoutDetail: UIViewController {
#IBOutlet weak var muscleLabel: UILabel!
var receivedName = ""
override func viewDidLoad() {
super.viewDidLoad()
muscleLabel.text = receivedName
}
}
Here is the getWorkout() function referenced above :
func getWorkout()-> [String] {
var musclesName = [String]()
let storedExercise = realm.objects(Workout1.self)
for exercise in storedExercise {
musclesName.append(exercise.exercise)
}
return musclesName
}
I'm having real difficulty with this and would very much appreciate some assistance, thanks.
Get didSelectRowAt out of prepare then
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
if cell == nil {
cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
}
let muscle = DBHelper.shared.getWorkout()[indexPath.row]
cell.textLabel?.text = muscle
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let name = DBHelper.shared.getWorkout()[indexPath.row]
self.performSegue(withIdentifier:"SegueName",sender:name)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let workoutDetailVC = segue.destination as! WorkoutDetail
workoutDetailVC.receivedName = sender as! String
}
Choosing a string in a UITableViewController, shows pic of the same name in another view controller, which works as it should.
But the problem is when I want to choose multiple strings to show multiple different pics.
I've been trying to add another IBOutlet, doubling stuff, but it was just showing me the same pic twice.
Any idea?
multiple selection = true
First VC segue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "tablesegue" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let selectedRow = indexPath.row
let passingVal = segue.destination as! Tabulka_data
passingVal.selectedImageName = self.tableItems[selectedRow]
}
}
}
secondVC:
#IBOutlet weak var pic: UIImageView!
var selectedImageName:String = ""
override func viewWillAppear(_ animated: Bool) {
self.pic.image = UIImage(named: selectedImageName)
}
two choices
You can try this
let yourDataArray = ["name 1","name 2","name 3","name 4","name 5"]
var imageSelected = [String]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return yourDataArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = yourTable.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = yourDataArray[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
imageSelected.append(yourDataArray[indexPath.row])
print(imageSelected)
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
for (index, element) in imageSelected.enumerated() {
if element == yourDataArray[indexPath.row] {
imageSelected.remove(at: index)
}
}
print(imageSelected)
}
You can use didSelectRowAt and didDeoRowAt to see which rows are selected, then just pass imageSelected to the second viewController
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
}