swift tableview sentence bug - ios

I am trying to make a tableview where the user can click on the cells so the cells open a new ViewController which sets the navbar title to the clicked cell's label.
It doesn't really work for me because when I click on a cell it opens a view which has the previously clicked cell's value (not the current cells value) and then again opens a new view where the title is the current cells's value.
I uploaded the viewcontrollers to a GitHub repo: https://github.com/SiposPtr/stackoverflow
var selectedValue: String?
var numberOfFileToLoad: Int = 1
let cellak = [
"Első",
"Második",
"Harmadik",
"Negyedik",
"Ötödik",
"Hatodik",
"Hetedik",
"Nyolcadik",
"Kilencedik"
]
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return cellak.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
cell.textLabel?.text = cellak[indexPath.row]
// Configure the cell...
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedValue = cellak[indexPath.row]
numberOfFileToLoad = indexPath.row + 1
performSegue(withIdentifier: "gotoSentences", sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "gotoSentences"{
let nextViewController = segue.destination as! ButtonEditViewController
nextViewController.title = selectedValue
nextViewController.numberOfFileToLoad = numberOfFileToLoad
}
}

It seems the segue is performed twice. If you have a segue connection from a table view cell to next view controller, the segue performed immediately after the cell is selected and didSelectRowAt method will be called after that.
You can get the selected row in prepare for segue method and pass the selected data to next view controller.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "gotoSentences"{
if let nextViewController = segue.destination as? ButtonEditViewController,
let indexPath = tableView.indexPathForSelectedRow {
nextViewController.title = cellak[indexPath.row]
nextViewController.numberOfFileToLoad = indexPath.row + 1
}
}
}

Related

How to pass data from NSObject to another ViewController when click on TableViewCell?

I have a ViewController1 with a TableView inside. What I want to do is go to ViewController2 and pass a piece of data along at the same time when user click on a TableViewCell.
For more details :
Each Cell have a itemId and other data which is store in NSObject class after pull from my API,which I use the data in TableViewCell class.So when I performSegue to ViewController2,I want to get the itemId in ViewController2
For now I able to go to ViewController2 when click on a tableViewCell by using this code:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//here I dont know how to get the itemId for that particular cell
performSegue(withIdentifier: "GoToSecondVc", sender: self)
}
I know I can pass my itemId like this:
var itemId : Int!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "GoToSecondVc" , let secondVC = segue.destination as? SecondViewController{
secondVC.itemId = self.itemId
}
The problem for now is I dont know how to get the itemId from NSObject when user click on any tableViewCell before I performSegue in didSelectRowAt section.
So how can I get the itemId in this case? Or is there a better way to do this?
I recommend to pass the selected index path in didSelectRowAt as sender:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "GoToSecondVc", sender: indexPath)
}
And use it in prepare(for segue, a temporary variable itemId is not needed. The code assumes that items is the data source array:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "GoToSecondVc" , let secondVC = segue.destination as? SecondViewController {
let indexPath = sender as! IndexPath
let item = items[indexPath.row]
secondVC.itemId = item.itemId
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let it = dataArrray[indexPath.row] as! ItemType
performSegue(withIdentifier: "GoToSecondVc", sender: it.itemID)
}

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?

How to change button title from table static cells?

I have HomeViewController that's segued modally to a Navigation Controller with an identifier of: pickSubjectAction
And on SubjectPickerTableViewController is where my subjects to choose. This is my code
import UIKit
class SubjectPickerTableViewController: UITableViewController {
var subjects:[String] = [
"English",
"Math",
"Science",
"Geology",
"Physics",
"History"]
var selectedSubject:String? {
didSet {
if let subject = selectedSubject {
selectedSubjectIndex = subjects.index(of: subject)!
}
}
}
var selectedSubjectIndex:Int?
override func viewDidLoad() {
super.viewDidLoad()
}
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 {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return subjects.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SubCell", for: indexPath)
cell.textLabel?.text = subjects[indexPath.row]
if indexPath.row == selectedSubjectIndex {
cell.accessoryType = .checkmark
} else {
cell.accessoryType = .none
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
//Other row is selected - need to deselect it
if let index = selectedSubjectIndex {
let cell = tableView.cellForRow(at: IndexPath(row: index, section: 0))
cell?.accessoryType = .none
}
selectedSubject = subjects[indexPath.row]
//update the checkmark for the current row
let cell = tableView.cellForRow(at: indexPath)
cell?.accessoryType = .checkmark
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "saveSelectedSubject" {
if let cell = sender as? UITableViewCell {
let indexPath = tableView.indexPath(for: cell)
if let index = indexPath?.row {
selectedSubject = subjects[index]
}
}
}
}
}
This is segued also with identifier: savedSelectedSubject.
Q1: How can i segued from button to the tableview controller?
I tried this but failed
Q2: How to changed the button titled from selected Subject?
my resources: https://www.raywenderlich.com/113394/storyboards-tutorial-in-ios-9-part-2
Any help is appreciated. Thanks
How can i segued from button to the tableview controller? I tried
this but failed
performSegueWithIdentifier expects a String format while you are sending it in Any format. Correct way for call this function is
self.performSegue(withIdentifier: "pickSubjectAction", sender: self)
How to changed the button titled from selected Subject?
I guess you want to reflect the selected subject in the controller presented after savedSelectedSubject segue. Let ViewController A be the one through which you are pushing/presenting and ViewController B be the one which is pushed/presented. Follow the following steps :
For this you need to fetch the destination controller (B) from prepare(for segue: UIStoryboardSegue, sender: Any?) function via segue.destination property.
Make a public variable in B in which you can set your selected subject.
Using that property you can show your selected subject title.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let B = segue.destination
// Assuming B's public var is named selectedSubject and is of String type
if let subject = self.selectedSubject {
B.selectedSubject = subject
}
}
In Controller B
override func viewWillAppear() {
super.viewWillAppear()
button.setTitle(self.selectedSubject, for: .normal)
}
// We already have the value of selectedSubject which we are using to set title for the button.

Move Text from cell to text label in a different view controller

I have created an app that displays 10 random numbers in a table view. This is the code I used
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ShowNumber", for: indexPath)
// Configure the cell...
cell.textLabel?.text = "\(indexPath.row + 1): \(Int(arc4random_uniform(10001)))"
return cell
}
Now I want to be able to click on one cell and be taken to another view controller and in the center of the page it displays the random number. I have the view controller all set up and linked to the original table view. I'm just having trouble passing my data through the segue. This is what I have so far. I know it unfinished, I just don't know what to do.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showRandomNumber" {
let controller = segue.destination as! ShowNumberTableViewController
let selectedRow = (tableView.indexPathForSelectedRow as NSIndexPath?)?.row ?? 0
controller.LabelText =
}
The LabelText is the name of the label that I want to pass the data to, but I don't know how to
Using the indexPathForSelectedRow, you can get a reference to the cell that triggered the segue. You can then access the textLabel within that cell, get its value, and pass it to the next view controller.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showRandomNumber" {
let controller = segue.destination as! ShowNumberTableViewController
if let indexPath = tableView.indexPathForSelectedRow {
let cell = tableView.cellForRowAtIndexPath(indexPath) as UITableViewCell
if let textToPass = cell.textLabel.text {
controller.labelText = textToPass
}
}
}
}
Then in ShowNumberTableViewController you want a var labelText and in your viewDidLoad() you can assign it to the textLabel in that view controller with
centerLabel.text = labelText
The way you are doing, the numbers will change when you scroll the table view. I think you should save the numbers in an array.
About how to grab the selected number in the prepareForSegue: I would do this way:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showRandomNumber" {
if let cell = sender as? UITableViewCell, indexPath = tableView.indexPathForCell(cell) {
let selectedNumber = numbers[indexPath.row]
controller.labelText = String(selectedNumber)
}
}
}

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

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)
}

Resources