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
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 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.
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 working in a UITableView which contains 5 rows ("a" to "e"), and when I click on one of the rows, it shows me in the next UITableView the letter I chose as a Header (with the prepareForSegue function). Actually, until this point it works perfectly.. BUT when I try to add more "headers" in the 2nd tableView after clicking in more than one row from the first UITableView, it just show me the last option (for example, if I click first in "a", then "d" and then "c"... the second UITableView just show me the row "c" as a header, not the other 2 rows).
How can I choose multiple rows and send those options to a second UITableView through a prepareForSegue function?
My line of codes for the first view are these:
let array = ["a", "b", "c", "d", "e"]
#IBOutlet var initialTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "segueA" {
if let destination = segue.destinationViewController as? Content {
if let selectedRow = initialTableView.indexPathForSelectedRow?.row {
destination.title = array[selectedRow]
}
}
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.array.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cellA", forIndexPath: indexPath) as UITableViewCell
cell.textLabel!.text = array[indexPath.row]
return cell
}
The second view contains these lines:
var contentArray:[String] = []
#IBOutlet var contentTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
contentArray.append(title!)
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return contentArray.count
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellContent = tableView.dequeueReusableCellWithIdentifier("cellContent", forIndexPath: indexPath) as UITableViewCell
cellContent.textLabel!.text = "Second test"
return cellContent
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return contentArray[section]
}
Thanks!
Joe.
For solving of you're issue.You should enabled multiple selection by :
tableView.allowsMultipleSelection = YES;
Than you should remember items you selected in first viewContoller. For convenience try to use:
var indexPathsForSelectedRows: [NSIndexPath]? { get }
And than send this information to the another viewController by segue.
Example:
let array = ["a", "b", "c", "d", "e"]
#IBOutlet var initialTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
initialTableView.allowsMultipleSelection = YES
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "segueA" {
if let destination = segue.destinationViewController as? Content {
if let selectedRows = initialTableView.indexPathsForSelectedRows {
//hear you have option to send items that are selected to another controller or send only indexPath.
}
}
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.array.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cellA", forIndexPath: indexPath) as UITableViewCell
cell.textLabel!.text = array[indexPath.row]
return cell
}
You have to store the selected rows yourself in a list or array
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//check if self._selectedIndices (your array) contains indexPath.row
//if yes then remove it from array
cell.accessoryType = UITableViewCellAccessoryType.None // remove check mark if you want to use it
//if no then add it to array
cell.accessoryType = UITableViewCellAccessoryType.Checkmark // add check mark if you want to use it
}
then in your prepareForSegue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// use self._selectedIndices to get the selected row indices
// self._dataSource[index] for the actual data
}
Just enable multiple selection on the tableview, and use the indexPathsForSelectedRows variant to get the full list. You can then either pass the whole list from your data source + the indexes, or map the indexes to the actual values.