I am having trouble with linking view controllers to table view cells. Basically I have 4 cells in my Table View, and I want each cell to present a separate view controller when clicked.
Here are my swift codes:
import UIKit
var orchard = ["Dog", "Cat", "Bird", "Fish"]
var myIndex = 0
class AnimalList: UITableViewController {
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return orchard.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = orchard[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
myIndex = indexPath.row
performSegue(withIdentifier: "segue", sender: self)
}
}
Here is my storyboard, as you can see I have 4 view controllers that I want to connect to the 4 table view cells.
storyboard
PS: My table view controller has already been embedded inside a navigation controller.
How do I do that? Thank you!
Embedded your TableViewController in Navigation Controller ( Most probably , you already did ) .
Select Yellow marked TableViewController click Right Mouse hold and put it to a view controller , release and select Manual Segue -> Show
Now select segue and rename it with unique Identifier . For every view controller repeat steps 2 & 3 .
Update tableView didSelectRowAt delegate function like below .
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath)
{
performSegue(withIdentifier: orchard[indexPath.row], sender: self)
}
Give a segue for the four ViewControllers and name it as vc1Segue, vc2Segue, vc3Segue, vc3Segue
And change your didSelectRowAt method like below
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
myIndex = indexPath.row
switch myIndex {
case 0:
performSegue(withIdentifier: "vc1Segue", sender: self)
case 1:
performSegue(withIdentifier: "vc2Segue", sender: self)
case 2:
performSegue(withIdentifier: "vc3Segue", sender: self)
case 3:
performSegue(withIdentifier: "vc4Segue", sender: self)
default:
print("Index greater than vcs")
}
}
Just now i done demo project with your requirements its working perfectly.
Step1: Prepare your story board as shown in below image.
step2: Give storyboard identifiers as dogID,catID,birdID,fishID to the respective viewController as shown in below image.
step3: Declare an array with the above identifiers just below your arched array.
var storyboardIds = ["dogID","catID","birdID","fishID"]
step4: Modify your didSelectRowAt method as shown in below code snippet.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
myIndex = indexPath.row
if let vc = storyboard?.instantiateViewController(withIdentifier: storyboardIds[myIndex]) {
self.navigationController?.pushViewController(vc, animated: true)
}
}
Create a segue for each of the 4 view controllers by ctrl+right click and dragging from table view controller to each of the view controllers. Give an identifier to the segues (e.g. "TableToViewController1", "TableToViewController2", etc)
Then in your didSelectRowAt do something like:
var segueIdentifier = ""
switch(indexPath.row) {
case 0: // first cell is selected
segueIdentifier = "TableToViewController1"
case 1:
segueIdentifier = "TableToViewController2"
case 2:
segueIdentifier = "TableToViewController3"
case 3:
segueIdentifier = "TableToViewController4"
}
performSegue(withIdentifier: segueIdentifier, sender: self)
What you can do is inside your
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
myIndex = indexPath.row
performSegue(withIdentifier: "segue", sender: self)
}
func you can check which index it is and based on that present the viewController you want.
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
myIndex = indexPath.row
if let animal = orchard[indexPath.row] as String? {
if animal == "dog" {
performSegue(withIdentifier: "dogViewController", sender: self)
}
}
}
In your storyboard you would create a segue from the viewController to all ur viewControllers and name the segues with something like dogViewController etc.
Related
Im a absolute beginner and my English isn't well .
I would like to create a program for a person who wants to learn German.
He can pick up a topic from a picker view and then display the translation in a table view with audio and a picture.
My problem right now is that I can send the topic(SegueStatus1) from the Picker view to my table view( which contains all the arrays), but I can not identify the array with the variable that I had before. I have now manually selected the Array(Aile).
The TABLEVIEW
import UIKit
// Two Arrays which can be chosen
var Aile = ["Anne","Baba","Dede"]
var ABC = ["A","B","C"]
var myIndex = 0
class TableEins: UITableViewController {
override func viewDidLoad() {super.viewDidLoad()}
//Two Strings from View before
var SegueStatus1: String?
var SegueStatus2: String?
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{return Aile.count}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = Aile[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
myIndex = indexPath.row
performSegue(withIdentifier: "AuswendigLernenSegue2", sender: self)
}
}
I am thankful for every help
EDIT :
override func prepare(for segue: UIStoryboardSegue, sender: Any?){
if (segue.identifier == "AuswendigLernenSegue")
{
let Status1: TableEins = segue.destination as! TableEins
Status1.SegueStatus1 = KonuT.text
}
I have a pickerView and a tableView both are working.
In the next step I want the pickerView and the tableView being connected.
The variable that determines which array I want to display is SeagueStatus1.
I want to use a solution that gets my variable right where the name of the array is needed.
Hope this helps:
class TableEins: UITableViewController {
// Avoid using magic strings.
let cellIdentifier = "cell"
let segueIdentifier = "AuswendigLernenSegue2"
// Always use lowercases for your variable and make them `let` unless you're going to manipulate them later. This tells everyone it's set only once and never modified.
// Also avoid global variables, I nested these inside the TableEins.
// Use snake case (ex: someVariable) for all variables. This lets someone identify the variable easily from classes and makes your code less confusing.
let aile = ["Anne","Baba","Dede"]
let abc = ["A","B","C"]
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return aile.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath)
cell.textLabel?.text = aile[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// This will always perform this segue no matter what cell you click on.
// If you want to perform this segue on only some of the cells, you need to check the index paths
performSegue(withIdentifier: segueIdentifier, sender: indexPath)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?){
// Guard is a great way to prevent from having too many nested if statetments and knowing your method execution stops here.
guard segue.identifier == segueIdentifier else { return }
// Get the index path from the sender
guard let indexPath = sender as? IndexPath else { return }
// Get your data using the index path and pass it to your view controller we are navigating to
// You were loading the TableEins as the destination view controller. Thats this class. You may have made a mistake here.
}
}
How to make Each Cell open the specific view for its indexpath.
In tableview didselect what should i do to make each cell open as its own indexpath so each cell have a different data in the next view
i am tryin when click in a cell in the tableview the next view present it self with it's own data as the next view contain a uitextview like in note app
what should i apply at row didselect
// MARK: -TableFunctions
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return SavingTasks.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let newtask = self.SavingTasks[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
cell.TheLabel?.text = newtask
return cell
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if(editingStyle == .delete)
{
self.SavingTasks.remove(at: indexPath.row)
self.TasksTable.deleteRows(at: [indexPath], with: .fade)
GetData()
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let NewIndex = self.SavingTasks[indexPath.row]
let view = self.storyboard?.instantiateViewController(withIdentifier: "TaskDetail") as! TaskDetail
view.SavingDetails = [NewIndex]
view.Index = indexPath.row
self.navigationController?.pushViewController(view, animated: true)
}
next class should be appeared
class TaskDetail: UIViewController {
var Delegate: NoteDetailDelegate!
var SavingDetails = [String]()
var Index: Int?
#IBOutlet weak var TaskDetailsFiled: UITextView!
#IBAction func SaveTDF(_ sender: UIButton) {
UserDefaults.standard.set(TaskDetailsFiled.text, forKey: "Saved")
self.navigationController?.popViewController(animated: true)
}
You can use a segue and prepare(for:sender:) to get the next view controller ready more easily than instantiating the view controller and popping it via code. Official documentation here and a sample app from Apple here
An implementation example:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "mysegue"{
if let nextViewController = segue.destination as? NextViewController{
nextViewController.Index = 2
}
}
}
A highlight from the official doc:
For example, if the segue originated from a table view, the sender parameter would identify the table view cell that the user tapped
If you want to stick with the code implementation, you can call view.myvariable = myvalue in your didSelect
I would like to know how to collect data from previous page when using UITableView.
It's hard to explain so I will give you an example.
Apple default calendar app has this feature in the New Event Page.
When you open the New Even page, you will see Never in Repeat field. To change this, you need to tap Never and go to the next page and select something like Every Week. If you select Every Week, it will go back to the first page and the Repeat field now shows Weekly.
I would like to make something similar but not sure how to set this up... My questions are; Do I need to use Segue? Do I need to use UITextField or UILabel for the cell? What triggers to pass the data?
MainviewController to add Below code
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// "SelectionSegue" is same as storyboard segue identifier
if segue.identifier == "SelectionSegue" {
(segue.destination as! SelectCategoryViewController).selectedCategoryValue = self.selectedCategoryLabel.text!
print(selectedCategoryLabel)
}
}
Set Segue Identifier in Storyboard
SelectedTableView
var selectedCategoryValue:String = ""
var CategeryArray = ["Food","Travel","Shopping","Card","MyReserve","Game","Songs","Movies","Entertainment","Business","Education","Finance","Drink","Sports","Social","Lifestyle"]
//Add TableView Delegate and Data Source Methods
extension SelectCategoryViewController: UITableViewDelegate,UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return CategeryArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TableViewCell")!
cell.textLabel?.text = self.CategeryArray[indexPath.row]
if self.CategeryArray[indexPath.row] == self.selectedCategoryValue {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
self.selectedCategoryValue = CategeryArray[indexPath.row]
self.tableView.reloadData()
}
}
My View Like
NavigationController -> Mainview -> SelectedTableView
there is a class MenuViewController in which the array recorded in the table is recorded:
import Foundation
import UIKit
class MenuViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var menuTableView: UITableView!
let myTitle = ["Помощь", "Информация", "Поддержка"]
override func viewDidLoad() {
super.viewDidLoad()
menuTableView.delegate = self
menuTableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return myTitle.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = menuTableView.dequeueReusableCell(withIdentifier: "MenuCell") as! MenuTableViewCell
cell.labelText.text = myTitle[indexPath.row]
return cell
}
}
What do you need to write in it to go to Info Controller?
I assume you are using storyboards. First you need to set up some sort of connection between your two viewcontrollers. You can do this by setting up a "segue". You hold ctrl+click drag from the first viewcontroller to the 2nd viewcontroller. It looks like this:
When you let go of the mouse, you will see this:
Click on Show. Now you will have created a segue.
Now you need to name it. So click on the segue that shows up in the storyboard. It is basically just an arrow from the Menu View Controller to the Info View Controller. On the right hand side you will see a place where you can name it (give it an identifier):
Now ... you have done all you needed to do in the storyboard. Now in your actual code in the MenuViewController, you need to associate clicking the tableviewcell. You do this by using the delegate method didSelectRowAt.
I see you have already set up the delegate with this line:
menuTableView.delegate = self
That ensures that didSelectRowAt will be called whenever the user taps on a row.
So now what you want to do is write the code to perform the segue:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "YourSegueName", sender: self)
}
Note:
Here is more information on interacting with a tableview row:
How to detect tableView cell touched or clicked in swift
Here is more information about segues:
IOS - How to segue programmatically using swift
There are many more customizations you can do ... such as passing data through to the next viewcontroller via the segues. Here's how:
Pass data through segue
implement UITableViewDelegate method:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//To InfoViewController I am considering you have created InfoViewController with XIB
let controller = InfoViewController(nibName: "YourNibName", bundle: nil)
//Present Your Controller
self.present(controller, animated: true) {
}
//Push Your controller if your view is already part of NavigationController stack
self.navigationController?.pushViewController(controller, animated: true)
}
Just add a
nextViewController.didMove(toParentViewController: self) inside a
"didSelectRowAt". Example given below.
This is for List a tableview cell:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "cell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! PatientFamilyDetailTableViewCell
cell.txt_patientName.text = patientname[indexPath.row]
// Configure the cell...
return cell
}
Now it's for Select a Table view cell:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) {
if cell.isSelected {
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "medtestmain") as! medTest
patient_id = relation[indexPath.row]
patient_name = patientname[indexPath.row]
UserDefaults.standard.set(patient_id, forKey: "patient_id")
UserDefaults.standard.set(patient_name, forKey: "patient_name")
self.addChildViewController(nextViewController)
nextViewController.view.frame = self.view.frame
self.view.addSubview(nextViewController.view)
nextViewController.didMove(toParentViewController: self)
}
}
}
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
}
}