TableView empties when interacting - ios

So I have 2 Views that are shown inside a UIView, based on what is selected on the SegmentViewController. I create dummy data, returning 20 row of a custom cell. This works great.
Everything is fine, till I interact with the TableView.
Bellow is my code:
GoalsViewController.swift
import UIKit
class GoalsViewController: UIViewController {
#IBOutlet weak var goalsTableView: UITableView!
let goalCellIdentifier = "goalCell"
override func viewDidLoad() {
super.viewDidLoad()
goalsTableView.delegate = self
goalsTableView.dataSource = self
goalsTableView.register(UINib(nibName: "GoalsViewCell", bundle: nil), forCellReuseIdentifier: goalCellIdentifier)
goalsTableView.reloadData()
}
}
extension GoalsViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = goalsTableView.dequeueReusableCell(withIdentifier: goalCellIdentifier, for: indexPath) as! GoalsViewCell
cell.goalTitle.text = "aaaaa"
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Selected \(indexPath.row)")
}
}
After any of the empty rows is selected, the didSelectRowAt is not called, so the cells are not there at all. I tried to find a solution, but I was only to find issues about empty lists, before being populated.
What could be the reason for the empty tableview?

I might be wrong here but one thing that I've noticed is that you are not implementing a function which sets the height of each cell.
// Specify the height of your cells
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100 // Or your given cell height.
}
So here is my theory: If you are using constraints something is missing and your cell's height can't be identified by constraints alone or you are not using constraints at all thus you must use heightForRowAt function to specify each cell's height.

I will explain what was the issue for people who probably did not know (like me).
So my UITableView is inside a UIView that changes based on what the user is selecting. In total I had 2 different Views that where switching. The reason that it was emptying it was because my parent ViewController, could not access the delegate for UITableView. To fix that, after adding a subview to the UIView, you need also to move the ViewController to the parent controller. In code it goes like this.
// Empty array of UIViewControllers
var views: [UIViewController]!
// Add the UIViewControllers to the array
views = [UIViewController()]
views.append(EventsViewController())
views.append(GoalsViewController())
for view in views {
// Needed to adjust the size of Subview to size of View
view.view.frame = containerView.bounds
// Add the subviews
containerView.addSubview(view.view)
}
// Bring the view in position 1 to the front of the UIView
containerView.bringSubviewToFront(views[1].view)
// Add Views[1] UIViewController as a child to the parent controller
self.addChild(views[1])
views[1].didMove(toParent: self)
// After done with everything with the UIViewController remove it
views[1].removeFromParent()
addChild Apple.com
didMove Apple.com

Related

Why did I get empty cells in UITableView?

I put my UITableView in UIScrollView > View > StackView.
And I implemented table view in View Controller as usual with numberOfRowsInSection and cellForRowAt. Here's my extension.
extension OrderViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("DEBUG: orderItems.count - \(orderItems.count)")
return orderItems.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: OrderCell.id, for: indexPath) as! OrderCell
cell.configure(orderItems[indexPath.row])
return cell
}
}
But my simulator actually shows empty cells. I already checked the orderItems array only has 2 members.
I guess it is because either auto layout or stack view. In the stack view, I gave height constraints for every views except table view since it has to have dynamic cell number.
I don't know what I have to change.
table view's attribute
This is because your tableview has full height with related your view. Just add on viewDidLoad
yourTableView.tableFooterView = UIView()
But if you want dynamic height for your tableview then do that;
Give a height constraint for your tableview
Create an IBOutlet for this constraint
After you reload your tableview
heightConstraint.constant = yourRowHeight * arrayCount
self.view.layoutIfNeeded()

Button not showing up in UITableViewCell

I have configured a tableview in my main storyboard which has a button in the prototype cell. However, when I run it, the tableview cells show up without the button. Here is an image of my storyboard:
Can someone explain why it won't show up when I run the program?
Checklist:
1. Set tableView's delegate and dataSource to the controller, i.e.
tableView.delegate = self
tableView.dataSource = self
2. Check if the height of tableViewCell is not 0.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 200.0 //Actual height of the cell
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 100.0
}
3. What constraints have you added to the button? Try adding centeredHorizontally and centeredVertically constraints to the UIButton.
The problem is with the height of the table cell. Button is not showing because the height of the cell is small. You must You have to implement the tableView heightForRowAt indexPath Method.
Before that Assign Delegate and DtataSource Method to the tableView.
override func viewDidLoad(){
super.viewDidLoad()
tableview.delegate = self
tableview.datasource = self
}
If already assign then.
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 105
}
Or I think you can also adjust the height from the Size Inspector check the custom height box and provide custom height. And also set proper constraint.
set background colour of button so that we can check button is created or not. or make sure you can add constraints of UIButton
Just place a break point on your UITableViewDataSource methods. If they are not calling then just go on your storyboard file and set the tableview delegate and datasource in your view controller.

UITableView item gets highlighted, and then gets deselected - Swift

I have a UIView with 3 nested UIViews. Their total width is 300% of screen. (100% each).
I'm changing AutoLayout priorities to bring the required on the screen and others off screen with buttons click from NavBar.
|uiview1| |uiview2| |uiview3|
uiview3 has a UITableView. It populates, scrolls perfectly, but on tapping an item, the item gets highlighted for a second and then released. The function 'didSelectRowAt' is NOT being called.
I have tried disabling every other gesture registered on this VC. The click is detected too but doesn't persist and gets deselected instantly.
//globally in VC
#IBOutlet weak var salamsTable: UITableView!
//in viewDidLoad
self.salamsTable.delegate = self
self.salamsTable.dataSource = self
//delegate functions
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
print (indexPath.row) // this never gets called
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.allSalam.count //works perfectly
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
var cell = self.msgsTable.dequeueReusableCell(withIdentifier: "messages") as! MessageCell
return cell // works perfectly
}
Visual Demo:
Not a Solution but an Alternate. Things worked out in another way. As you can see in the Demo GIF attached in the question, the cells are being highlighted properly. So i add the delegate method didHighlightRowAt and it worked like a charm.

UITableViewController shows nothing but horizontal lines

I'm just starting with Swift and xCode, and currently messing around with UITableView, I can't manage to just write 'test' into a table.
I created a UITableViewController in the Storyboard, specified a custom class for it (my swift file below), filled in 'ClientCell' as a reuse identifier of the cell and the code is as follows:
class TableViewController: UITableViewController {
#IBOutlet var clientTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
clientTable.dataSource = self.dataSource;
clientTable.delegate = self;
}
func numberOfRowsInSection(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ClientCell", forIndexPath: indexPath) as! CustomTableViewCell
cell.tableLabel.text = "test"
return cell
}
}
In the storyboard, I added a 'UILabel' into the prototype cell, and created an outlet for it named 'tableLabel' in the CustomTableViewCell.swift.
I confused by all the side-things I've to consider when doing something as simple as this.
When I run it, the simulator just shows a table with a lot of horizontal lines, but nowhere it says 'test'.
You haven't used the numberOfRowsInSection method.....
Additionally you also need to set the table view's data source and delegate to be the class you are writing these methods in (in case you haven't).
At a bare minimum you need this:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1 // this should really be from your data source
}
If you create a UITableViewController subclass in Xcode the template will have commented-out versions of all the methods you likely will want to fill out.

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. :)

Resources