Xcode Trigger Action after Cell is Clicked in Swift - ios

I am relatively new to programming in general (this is my first year learning it at school) so please explain in as easy a way to grasp as possible.
I am using UITableViewController to create a table view and I want to be able to add a string to a cell if it is empty (I think I have to add it to the array "phrases", but correct me if I am wrong) and display the contents of the cell if it contains a string. I know it has something to do with NSIndexPath but I don't know where to put the code.
class MyPhrases: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
var phrases = []
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return phrases.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell")!
cell.textLabel
return cell
}
}
Sorry if I messed up the formatting of the code this is my first question.
Thanks in advance.

You are correct, you have to declare your array with phrases strings:
var phrases = ["welcome to stackoverflow", "second phrase", "third phrase"]
And change your cellForRowAtIndexPath method like this:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell")!
cell.textLabel.text = phrases[indexPath.row]
return cell
}
Index path describes the position of cell in table view. It has two important properties: row and section. Since your table view has only one section, you get the phrase to display from array by row number.

I think you need
cell.textLabel.text = phrases[indexPath.row]
but you will also need some code elsewhere to populate the array. for testing, you could try initialising the array - just to make sure you're seeing something in the tableView. You can initialise the array like this
var phrases = ["first", "second", "third"]

Related

Table View Cells Double When I Add A New Cell - Swift 4

I am currently making a golf round tracker that displays your rounds in a table view with the cells being xibs. When I add one round, it appears fine on the table view, but when I add another round it adds that cell and doubles the cells. Here is a picture of what happens: https://i.stack.imgur.com/SOgN4.png. Here is my code:
class RoundDisplay: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
arrayOfCellData.append(roundData(id : arrayOfCellData.count + 1, date : datePlayedFC, course : currentCourse, score : String(score1234) ))
tableView.reloadData()
print(arrayOfCellData)
}
override func numberOfSections(in tableView: UITableView) -> Int {
//Shows how many cells it should display; number of current cells
return arrayOfCellData.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//Shows how many cells it should display; number of current cells
return arrayOfCellData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//Defines what xib to use for cells
let cell = Bundle.main.loadNibNamed("TableViewCell", owner: self, options: nil)?.first as! TableViewCell
//Adds array data to each cell
cell.DateLbl.text = arrayOfCellData[indexPath.row].date
cell.CourseName.text = arrayOfCellData[indexPath.row].course
cell.ScoreLbl.text = arrayOfCellData[indexPath.row].score
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
//Shows how high to make cells; height of xib
return 68
}
}
The number of sections function needs to be set to one. I realized that it decided how many cells it should show for the data from the array. Which means if you have the function set as I did, for instance, if you had two sets of data in the array, it would put two cells for each data. Thanks to #Magnas and #vacawama for the help!

How to access to a textLabel in a static cell

After much searching and reading I unfortunately do not come from the following. I want to use static tables to display certain data. (Are there better options?)
In my view I first put an onion picture with a container view underneath. The container view again refers to a Table View Controller.
I made an outlet from the cells and then I thought I could easily adjust the text.
Now I want to change the text of the fields in the table, but unfortunately I do not succeed.
When I start the app then the table is completely empty as seen on the screenshot.
What am I doing wrong ?
class TableViewController: UITableViewController {
var data: [String] = ["Muis", "Aap", "Koe", "Vis"]
override func viewDidLoad() {
super.viewDidLoad()
}
// 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 data.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let iets = data[indexPath.row]
cell.textLabel?.text = iets
return cell
}
}
If you want to use static cells
Forget dequeueing UITableViewCell instances and all tableview data source and delegate methods.
In Interface Builder select the table view and select Static Cells from the Content popup
Drag the amount of static cells you need into the canvas
In the view controller declare IBOutlets and connect them directly to the UI elements in the cells
You need to change your way of thinking for this one. You do not own the cells, the UITableView does. It will provide cells as it seems fit by using your implementations of UITableViewDataSource:
func numberOfSections(in: UITableView) -> Int
func tableView(UITableView, numberOfRowsInSection: Int) -> Int
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell
Normally, the texts (your actual data) would be held in a list available to this data source.
Example:
var data: [String] = []
// Other functions
func numberOfSections(in: UITableView) -> Int {
return 1
}
func tableView(UITableView, numberOfRowsInSection: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "YOUR_IDENTIFIER")
cell.text = data[indexPath.row]
return cell
}
Now, if you want to change this cell's text, all you have to do is update your data list and reload the data.
What I have done after a lot of testing and reading. I have create a segue to the statutable class.
if (segue.identifier == "myEmbeddedSegue") {
let childViewController = segue.destination as! hondDetialTableViewController
childViewController.hondId = hondData["hondId"]!
}
In this segue I send only the hondId, everything else i ask entities.
I'm sorry but this is not at all how UITableView works. The UITableViewCell that you define in the Xib/Storyboard within the tableview are just "models" or templates, they don't actually exists until you dequeue them.
You can read how UITableView works here: http://www.thomashanning.com/uitableview-tutorial-for-beginners/
You have to return numberOfSections > 0 if you want anything displayed in your tableview; similarly, that section has to also have numberOfRows > 0 otherwise again, nothing will be displayed (ok, maybe headers and footers if those are properly setup).
At any rate, cells are only accessible after you dequeue them. Creating an outlet in a XIB to a UITableViewCell is useless in most cases.
You can explore other options, such as UIStackView, or maybe what you need is just plain custom UIView with labels that you properly set and layout using NSLayoutConstraints. There are plenty of resources out there, this is just one I quickly Googled for you to get started: https://www.youtube.com/watch?v=de0sthle44I
Good Luck.

TableViewController Detect Row Tap with Static Cells

I'm using a TableViewController that has a table with 2 sections of static cells. This is embedded in a view controller. I cannot get didSelectRowAtIndexPath to run when I tap the cells. I've already check all of the usual suspects from this question as well as this one. When I try with a table view inside a viewcontroller with a dynamic table, I am able to get it to work just fine. Is there an issue with using a TableViewController with static cells that would not allow for using didSelectRowAtIndexPath?
Here is what I have in the custom class for the TableViewController:
import UIKit
class OptionTableViewController: UITableViewController {
#IBOutlet var optionsTable: UITableView!
let numberOfRows = [7,2]
let cellIdentifier = "OptionCells"
override func viewDidLoad() {
super.viewDidLoad()
self.optionsTable.delegate = self
self.optionsTable.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 2
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
var rows = 0
if(section < numberOfRows.count){
rows = numberOfRows[section]
}
return rows
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
print("You selected cell #\(indexPath.row)!")
}
}
Update:
I tried replacing the tableviewcontroller and the viewcontroller it was embedded in but I am still not able to get didSelectRowAtIndexPath to run.
Update 2:
Does anyone know if this is possible in Swift 3? I found a working example using Swift 2.2 with a tableviewcontroller and static cells here. Maybe there is a bug doing this with Swift 3?
Wow, so it turns out that didSelectRowAtIndexPath is no longer correct in Swift 3. The correct usage is now didSelectRowAt. I didn't see this mentioned anywhere except this question which I stumbled upon.
This:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You selected cell #\(indexPath.row)!")
}
Not This:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
print("You selected cell #\(indexPath.row)!")
}
It's possible you have the wrong table view hooked up. Normally, a UITableViewController has it's tableView in the view property and you don't need to set up the data source and delegate programatically.

Swift UITableView didSelectRowAtIndexPath not getting called

New to IOS development and am having trouble with handling cell selection on a table. Whenever I select, the method is not getting called below - any idea why?
My project structure is:
View Controller -> View -> Table View
The below code demonstrates the method calls. The others get called no problem! I know touch is working as pull down successfully refreshes and on clicking a cell it does become highlighted.
import UIKit
class ViewController: UIViewController, UITableViewDelegate
{
let blah = ["blah1"]
//How many sections are in the table?
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
//How many rows? (returns and int)
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return blah.count
}
//table contents for each cell?
//Each time this is called it'll return the next row and thus build a table...
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
print("Populating each cell of table view!\n")
tableView.rowHeight = 80.0
var cell = UITableViewCell()
var(a) = blah[indexPath.row]
var image : UIImage = UIImage(named: a)!
cell.imageView.image = image
return cell
}
//Code Cell Selected
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
println("You selected cell #\(indexPath.row)!")
}
func tableView(tableView: UITableViewDelegate, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
print("wananananaanan" )
println("You deselected cell #\(indexPath.row)!")
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Everybody is mentioning to set dataSource and delegate of the tableView.
But after setting also not working fine then sometimes it may happen because of none or disable selection of table view.
To enable it
Go to storyboard -> Select tableView -> click on the attribute inspector ->go to selector -> Select selection as single selection (or multiple selection according to the requirements.)
Please find attached screenshot for your suitability.
You have to set an #IBOutlet to the tableView in you ViewController and set as it's delegate and dataSource to you can see the data an respond to changes in the tableView.
Something like this :
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
}
And implements the UITableViewDataSource protocol too.
Or you can too in the Interface Builder set the ViewController as it's delegate and dataSource (more easy to do I think) and avoid to set manually in code like above. Is up to you.
I hope this help you.
SWIFT 3
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Do here
}
Use the above delegate method in swift 3
Couple of checks that can help you:-
myTableView.allowsSelection = true
myTableView.delegate = self
Make sure you written didSelectRowAt correctly:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
If you are using UIButton on UITableViewCell then it overlaps cell so check Solution here
I faced the same issue when compared two identical code examples where one was working well and the other was not calling didSelectRowAtIndexPath
Take a look at two possible ways to solve the issue:
1) In the code itself:
#IBOutlet weak var table: UITableView!
override func viewDidLoad() {
table.delegate = self
table.dataSource = self
//data source might be already set if you see contents of the cells
//the main trick is to set delegate
}
2) Using Storyboard or Document Outline (which was the problem in my case cause storyboard changes are not visible in .swift controller classes.
Open Document Outline and Control + Press your TableView
you will see two outlets called "delegate" and "dataSource"
drag them 1 by 1 to the containing ViewController (right onto the yellow circle)
That's it!
Another caveat is tap gesture recognizers. It's a common use case to use tap gesture recognizer to handle different logic within your view controllers with table views, whether that's exiting touch control or first responders.
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(viewTapped))
view.addGestureRecognizer(tapGesture)
E.G. This line of code handles dismissing a date picker in my application and prevents my tableview from calling didSelectRow delegate method
You have to use this: First take a look what are you extending and then use the tableView method.
class YourViewController : UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var mUITableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// We need to tell to UITableView that we will add the data by ourselves
self.mUITableView.delegate = self
self.mUITableView.dataSource = self
// Register the UITableViewCell class with the tableView
self.mUITableView?.registerClass(UITableViewCell.self, forCellReuseIdentifier: self.cellIdentifier)
// Setup table data
getEvents()
self.mUITableView.allowsSelection = true
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
// here to create you cell view
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("You selected cell #\(indexPath.row)!")
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "subtitleCell")
cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
cell.textLabel?.text = "\(tableData[indexPath.row].name) - (\(tableData[indexPath.row].eventStateId))"
cell.detailTextLabel?.text = tableData[indexPath.row].lastUpdate
return cell
}
}
Another reason you may write this function which allowed to click under condition
func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
if(indexPath.section == 1){
return true
}
return false
}
Another caveat which took me ages to figure out is to make sure that all three of your Table View, your Cell and your Content View all have User Interaction Enabled. Then in Swift 4, at least, you can use:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
if you are editing your tableView:
tableView.allowsSelectionDuringEditing = true
Another thing to check is the access level for your class & method:
I had a Swift UIViewController class marked #objc public, to make it visible to my objective-c code.
In this context you must add public access to this function, or it will not be called.
public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
Nothing happened till I've cleaned and built again. :)

How to add items to UITableView using Swift?

i have been busting my brain trying to figure out how this works, but i can't seem to get it. i have tried using other tutorials, but with the many beta releases, everything keeps changing. i am fairly new to IOS development, so i'm kind of struggling.
in storyboard i have UITableView, which contains a cell with the identifier "myCell".
here's what i have so far. when i run the IOS simulator, nothing is presented on the table view.
any suggestions on how to fix this?
class ViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = "Cell #: \(indexPath.row)" // display the row number
return cell
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10; // testing out with 10 cells
}
}
Add the function
optional func numberOfSectionsInTableView(tableView: UITableView) -> Int
and return the number of sections you want.
You should make sure in the storyboard your UITableViewController has the class ViewController like so:
and that ViewController is both the delegate and datasource of the UITableViewController like so (Referencing Outlets):
You should also check that your UITableViewController is set to initialViewController if you don't see any lines at all (check the one at the bottom).

Resources