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

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!

Related

tableView data gets reloaded every time I scroll it

So every time I scroll my tableView it reloads data which I find ridiculous since it makes no sense to reload data as it hasn't been changed.
So I setup my tableView as follows:
func numberOfSections(in tableView: UITableView) -> Int {
return self.numberOfElements
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 6
}
My cells are really custom and they require spacing between them. I couldn't add an extra View to my cell to fake that spacing because I have corner radius and it just ruins it. So I had to make each row = a section and set the spacing as a section height.
My cell has a dynamic height and can change it's height when I click "more" button, so the cell extends a little.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if self.segmentedControl.selectedSegmentIndex == 0 {
if self.isCellSelectedAt[indexPath.section] {
return self.fullCellHeight
} else {
return self.shortCellHeight
}
} else {
return 148
}
}
And here's how I setup my cell:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = UITableViewCell()
if self.segmentedControl.selectedSegmentIndex == 0 {
cell = tableView.dequeueReusableCell(withIdentifier: String.className(CurrentDocCell.self)) as! CurrentDocCell
(cell as! CurrentDocCell).delegate = self
(cell as! CurrentDocCell).ID = indexPath.section
} else {
cell = tableView.dequeueReusableCell(withIdentifier: String.className(PromissoryDocCell.self)) as! PromissoryDocCell
}
return cell
}
So I have a segmentedControl by switching which I can present either one cell of a certain height or the other one which is expandable.
In my viewDidLoad I have only these settings for tableView:
self.tableView.registerCellNib(CurrentDocCell.self)
self.tableView.registerCellNib(PromissoryDocCell.self)
And to expand the cell I have this delegate method:
func showDetails(at ID: Int) {
self.tableView.beginUpdates()
self.isCellSelectedAt[ID] = !self.isCellSelectedAt[ID]
self.tableView.endUpdates()
}
I set a breakpoint at cellForRowAt tableView method and it indeed gets called every time I scroll my tableView.
Any ideas? I feel like doing another approach to make cell spacing might fix this issue.
A UITableView only loads that part of its datasource which gets currently displayed. This dramatically increases the performance of the tableview, especially if the datasource contains thousands of records.
So it is the normal behaviour to reload the needed parts of the datasource when you scroll.

Grouping cells, adding text above or below cells & empty space in Tableview

I'm trying to achieve something like the image at the bottom of the page . Specifically:
Add spacing between each cells (in a different group you could say.)
Add text above or below the cell.
Have empty space everywhere else with no cells.
I want everything to look exactly like this image.
(Ignore the text, navigation bar, and anything inside the cells.)
I have already tried this and came out with this image below:
This is my code from what I have tried:
let data = [["0,0", "0,1", "0,2"], ["1,0", "1,1", "1,2"]]
let headerTitles = ["Some Data 1", "KickAss"]
// MARK: - TableView Data Source Methods
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let cellText = data[indexPath.section][indexPath.row]
cell.textLabel?.text = cellText
return cell
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section < headerTitles.count {
return headerTitles[section]
}
return nil
}
TableView State This document will help you for tableview state. (loading, data, empty states)

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.

iOS self sizing table views inside self sizing table views

enter image description here
I have a tableView with X number of cells, every cell has 1 table view with N number of cells.
How to make every x cell fits the the content size of it's sub tableView.
I think you should use table view with sections, so your X number of cells will be the number of sections in this case, and N number of cell will be number of rows in that section.
//MARK: TableView Delegate
func numberOfSections(in tableView: UITableView) -> Int {
return X
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "YourIdentifier") as? YourTableViewCell
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numberOfRows
}
Hope that is what you need.

How do I set the height for a custom UITableView?

I will be using a dynamic number of cells and resizing the height of the table on that basis. I could work out how to do this myself by I can't seem to resize the table. Whether I use 100 cells or 10 the view is set at the same height.
class generalTableViewController: UITableViewController {
override func viewWillAppear(_ animated: Bool) {
tableView.rowHeight = UITableViewAutomaticDimension
// self.tableView.contentSize.height = 2000
// self.tableView.frame.size.height = 2000
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1000
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
return cell
}
}
UITableViewControllers generally take over the entire view. To occupy only a portion of the view with a UITableView use a UIViewController.
You should use a UIViewController subclass rather than a subclass of UITableViewController to manage a table view if the view to be managed is composed of multiple subviews, only one of which is a table view. The default behavior of the UITableViewController class is to make the table view fill the screen between the navigation bar and the tab bar (if either are present).
See here for Apple guidance. You basically just need to take care of some of the things the controller would normally handle for you.

Resources