How to access override func tableView property from prepareForSegue method inside same class - ios

I have two viewControllers.First one is a tableViewController and second one is a webViewController.I want to pass data from 1st vc to 2nd vc using segue. For this reason i wants the value of "chosenCellIndex" from override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) to prepareForSegue method. But i can not access the chosenCellIndex value from prepareForSegue method. Please help.
class NewsTableViewController: UITableViewController {
#IBOutlet var Alphacell: UITableView!
var chosenCellIndex = 0
//var temp = 0
var newspaper = ["A","B","C"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return newspaper.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Alphacell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = newspaper[indexPath.row]
// Alphacell.tag = indexPath.row
//Alphacell.addTarget(self, action: "buttonClicked:",forControlEvents: UIControlEvents.TouchUpInside)
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
chosenCellIndex = indexPath.row
//println(chosenCellIndex)
// Start segue with index of cell clicked
//self.performSegueWithIdentifier("Alphacell", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let secondViewController = segue.destinationViewController as WebViewController
secondViewController.receivedCellIndex = chosenCellIndex
println(chosenCellIndex)
}
}

In order to get chosen cell index you need to get indexpath for selected row, then you need to get section or row index from indexpath.
See the below code for getting row index
let indexPath = tableName.indexPathForSelectedRow
let section = indexPath?.section
let row = indexPath?.row

Make sure you have set the identifier on the segue in storyboard then do:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "someIdentifier"{
let secondViewController = segue.destinationViewController as? WebViewController
//Also, make sure this is the name of the ViewController you are perfoming the segue to.
secondViewController.receivedCellIndex = chosenCellIndex
print(chosenCellIndex)
}
}
Also, what version of Xcode and Swift are you using? println() is now just print().

best way to do that is from did select row function, that example
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let objects = newspaper[indexPath.row]
let vc = storyboard.instantiateViewControllerWithIdentifier("someViewController") as! UIViewController
vc.someString = objects.title
self.presentViewController(vc, animated: true, completion: nil)
}
and prepareForSegue use this code :
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let path = self.tableView.indexPathForSelectedRow()!
segue.destinationViewController.detail = self.detailForIndexPath(path)
}

Related

I want to display Array from UITableView to the next viewController using didSelectRowAt

I want the quizNumber to return the quizNumberArray depending on which cell is selected.
For example, if the user selected the first cell the quizNumber returns 1
Inside the UITableViewController
let quizNumberArray = [1,2,3,4,5,6,7,8,9,10]
var quizNum = Int()
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = storyboard?.instantiateViewController(withIdentifier: "toQuestionVC") as? QuestionVC
quizNum = quizNumberArray[indexPath.row]
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let identifier = segue.identifier {
if identifier == "toQuestionVC" {
let questionController = segue.destination as! QuestionVC
questionController.quizNumber = quizNum
}
in the next ViewController
class QuestionVC : UIViewController {
var quizNumber = Int()
func updateQuestion(){
if quizNumber == 1 {
//.....
}
}
}
But the quizNumber return 0.
Try this Code:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = storyboard?.instantiateViewController(withIdentifier: "toQuestionVC") as? QuestionVC
vc?.quizNumber = quizNumberArray[indexPath.row]
navigationController?.pushViewController(vc!, animated: true)
}
and remove the segue to work the above code

Editing table row cell swift 3

I am trying to edit the table row cell. I have different tableViewController set up to display/edit the current events when they touch on the displayed events from initial tableViewController. Whenever I edit an event and hit save, it goes back to the main viewController where i am initially displaying my events, but it doesn't display the edited events. it keeps showing the original events.
Here is the portion of my main tableView file where i am displaying my events:
class EventsTable: UIViewController, UITableViewDataSource, UITableViewDelegate {
var tableData = ViewController()
#IBOutlet weak var table: UITableView!
#IBAction func saveToMainViewController (change:UIStoryboardSegue) {
let editViewController = change.source as! EditEventsTableViewController
let index = editViewController.index
let titleString = editViewController.editedTitle
tableData.eventsArray[index!].title = titleString
table.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return tableData.eventsArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomeCell
cell.eventTitle.text = tableData.eventsArray[indexPath.row].title
cell.eventLocation.text = tableData.eventsArray[indexPath.row].location
cell.eventDateAndTime.text = tableData.eventsArray[indexPath.row].date
return cell
}
//function to delete cell and saves it
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
tableData.eventsArray.remove(at: indexPath.row)
table.reloadData()
let savedEvents = NSKeyedArchiver.archivedData(withRootObject: tableData.eventsArray)
UserDefaults.standard.set(savedEvents, forKey: "savedEvents")
UserDefaults.standard.synchronize()
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "edit" {
var path = table.indexPathForSelectedRow
let detailViewController = segue.destination as! EditEventsTableViewController
detailViewController.index = path?.row
detailViewController.eventsArray = tableData.eventsArray
}
}
Here is the other tableViewController where i edit my data
class EditEventsTableViewController: UITableViewController {
#IBOutlet weak var txtEditTitle: UITextField!
var index:Int!
var eventsArray = [Event]()
var editedTitle: String!
override func viewDidLoad() {
super.viewDidLoad()
txtEditTitle.text = eventsArray[index!].title
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.section == 0 && indexPath.row == 0 {
txtEditTitle.becomeFirstResponder()
}
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "save" {
editedTitle = txtEditTitle.text
}
}
}
incase you guys need a better look at the project,
download link for the project
Probably in EditEventsTableViewController you missed table view reloading?
override func viewDidLoad() {
super.viewDidLoad()
tableView.reloadData()
txtEditTitle.text = eventsArray[index!].title
}
It's unclear, where do you provide data for EditEventsTableViewController. Is it static table view, designed in storyboard?

Swift: Passing data from a tableView in a ViewController to another ViewController

I'm trying to pass the indexPath.row data from the selected cell to the next view controller using both the didSelectCellAtIndexPath and the prepareForSegue methods but the value isnt passing through.
Code for both ViewControllers is show below:
import UIKit
class MainMenu: UIViewController, UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource {
// array of the menu options
let mainMenuOptions = ["Exercises 1", "Exercises 2", "Exercises 3"]
// UITableView
#IBOutlet weak var exerciseOptions: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
exerciseOptions.delegate = self
exerciseOptions.dataSource = self
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Table configuration
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "ExercisesTableViewCells"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! ExercisesTableViewCell
cell.textLabel!.text = mainMenuOptions[indexPath.row]
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
// Segue to VC based on row selected
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 0{
self.performSegueWithIdentifier("SegueToExercises", sender: self)
}
else if indexPath.row == 1{
self.performSegueWithIdentifier("SegueToExercises", sender: self)
}
else{
self.performSegueWithIdentifier("SegueToReminders", sender: self)
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "SegueToExercise"){
let viewController = segue.destinationViewController as? ExerciseMenu
viewController!.mainMenuValue = exerciseOptions.indexPathForSelectedRow!.row
}
}
For the Second View Controller:
import UIKit
class ExerciseMenu: UIViewController, UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var exerciseOptionsTitle: UILabel!
#IBOutlet weak var exerciseOptionsTable: UITableView!
#IBAction func beginWorkout(sender: AnyObject) {
}
// receives data from MainMenu
var mainMenuValue: Int!
override func viewDidLoad() {
super.viewDidLoad()
exerciseOptionsTable.delegate = self
exerciseOptionsTable.dataSource = self
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "ExerciseMenuCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! ExercisesTableViewCell
cell.textLabel!.text = String(mainMenuValue)
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
See this thread for possible explanations for this behavior.
The first step of troubleshooting would be to put a breakpoint in your prepareForSegue method to see if exerciseOptions.indexPathForSelectedRow is already nil at that point, in which case something is happening before the segue even occurs that's messing with the value (which the link above can help you diagnose).
Try making a property in your table view controller called something like selectedRow, and in didSelectRowAtIndexPath, set self.selectedRow = indexPath.row. This way you have your own variable that'll be more reliable than exerciseOptions.indexPathForSelectedRow. Then change the code in prepareForSegue appropriately. So to give you the full methods as I'm envisioning them:
(As a property of the first view controller) var selectedRow: Int?
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 0{
self.performSegueWithIdentifier("SegueToExercises", sender: self)
self.selectedRow = 0
}
else if indexPath.row == 1{
self.performSegueWithIdentifier("SegueToExercises", sender: self)
self.selectedRow = 1
}
else{
self.performSegueWithIdentifier("SegueToReminders", sender: self)
self.selectedRow = indexPath.row
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "SegueToExercise"){
let viewController = segue.destinationViewController as? ExerciseMenu
viewController!.mainMenuValue = self.selectedRow!
}
}
Disclaimer: I'm still learning Swift, so my judgment regarding optionals/optional unwrapping might be unideal for a technical reason I'm not aware of, but the overall theory here is sound, I think.

Why is this value not passing between my ViewControllers?

I'm coding a multi-step sign-up flow, but cannot get the cell labels to pass between each viewcontroller.
Here is the code from the first viewController:
class FirstVC: UIViewController, UITableViewDelegate {
#IBOutlet weak var tableview: UITableView!
var userGoalOptions = ["Lose Fat","Gain Muscle", "Be Awesome"]
var selectedGoal: String = ""
override func viewDidLoad() {
super.viewDidLoad()
self.title = "What Is Your Goal?"
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell1")! as UITableViewCell
cell.textLabel?.text = userGoalOptions[indexPath.row]
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return userGoalOptions.count
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let indexPath = tableView.indexPathForSelectedRow
let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!
selectedGoal = currentCell.textLabel!.text!
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "secondSeque") {
let vc = segue.destinationViewController as! SecondVC
vc.userGoal = selectedGoal
}
}
The segue (secondSegue) is connected to the table view cell in Interface Builder
In my destination viewcontroller (vc) I have an empty userGoal variable, but when I try to print the contents it returns nothing.
I know variations of this question have been asked numerous times, but I can't seem to find (or maybe understand) what I'm messing up.
Assuming the segue is connected to the table view cell in Interface Builder the cell is passed as the sender parameter in prepareForSegue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "secondSeque") {
let selectedIndexPath = tableView.indexPathForCell(sender as! UITableViewCell)!
let vc = segue.destinationViewController as! SecondVC
vc.userGoal = userGoalOptions[selectedIndexPath.row]
}
In this case didSelectRowAtIndexPath is not needed and can be deleted.
Apart from that it is always the better way to retrieve the data from the model (userGoalOptions) than from the view (the table view cell) for example
Do
let indexPath = tableView.indexPathForSelectedRow
selectedGoal = userGoalOptions[indexPath.row]
Do not
let indexPath = tableView.indexPathForSelectedRow
let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!
selectedGoal = currentCell.textLabel!.text!
The prepareForSegue Should not be part of the table view function, you have copied it into a place where it is never called. Move it out and place a break point on it to see that it is being called.

How do I send specific data based on which cell is clicked?

I have a tableview with a bunch of concerts, and when x cell is clicked, I want the artist of that concert to populate the new tableView. Below is the code for the first view controller (the view controller with all the concerts).
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView1: UITableView!
var arrayOfConcerts: [concert] = [concert]()
override func viewDidLoad()
{
super.viewDidLoad()
self.setUpConcerts()
self.tableView1.rowHeight = 145.0
}
func setUpConcerts()
{
var ACL = concert(imageName: "ACL2015.png")
let Landmark = concert(imageName: "Landmark.png")
let BostonCalling = concert(imageName: "BostonCalling.png")
let Lolla = concert(imageName: "Lolla.png")
arrayOfConcerts.append(ACL)
arrayOfConcerts.append(Landmark)
arrayOfConcerts.append(BostonCalling)
arrayOfConcerts.append(Lolla)
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayOfConcerts.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = self.tableView1.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CustomCell
let concerts = arrayOfConcerts[indexPath.row]
cell.setCell(concerts.imageName)
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
performSegueWithIdentifier("concertartist", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
}
}
Below is the code for the Artist View Controller (the second
viewcontroller). This tableView should be populated with specific
artists.
How would I go about doing that?
class ArtistConcerts: UIViewController, UITableViewDataSource, UITableViewDelegate {
var arrayOfArtists: [artist] = [artist]()
#IBOutlet weak var tableViewArtists: UITableView!
override func viewDidLoad()
{
super.viewDidLoad()
self.setUpArtists()
}
func setUpArtists()
{
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayOfArtists.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableViewArtists.dequeueReusableCellWithIdentifier("", forIndexPath: indexPath) as! CustomCell
let artists = arrayOfArtists[indexPath.row]
cell.setCell(artists.imageNameArtist)
return cell
}
}
You need to do this in the prepareForSegue method.
let vc = segue!.destinationViewController as! ArtistConcerts
if let rowSelected = tableView.indexPathForSelectedRow()?.row {
vc.arrayOfArtists = artistsPerforming[0]//this is an array
}
then, set whatever data you need to actually populate the tableView in that new view controller. I am not 100% sure on what you are trying to do though. Does my answer make sense?
you can send data once the cell is pressed to another viewcontroller by using didSelectRowAtIndexPath or prepareForSegue or didSelectRowAtIndexPath + prepareForSegue
let's say you are using prepareForSegue, things you will need
the segue identifier name
cast the destinationController to the controller you want to send the data
the indexPath.row where the cell was selected
then set the variable or variables or data structure that should receive data
Create a segue when you pressed CTRL + Drag from your cell into another viewcontroller
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "Name_Of_Segue"
{
let destination = segue.destinationViewController as! NAME_Of_ViewController
let indexPath = mytableview.indexPathForSelectedRow!
let data = arrayOfArtists[indexPath.row]
destination.artist = data
}
mytableview is an IBOutlet from your tableview
artist is a variable that is declared in your destination controller
destination.artist = data this line of code is passing data from the specific cell then send it to your destination cell

Resources