I have UITableView with methods:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
override func numberOfSections(in tableView: UITableView) -> Int
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
So, the problem is that Xcode runs at first
override func numberOfSections(in tableView: UITableView) -> Int
which returns me 1.
Later it runs override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int which also returns me 1.
BUT I do not know why after these 2 methods it does not run cellForRowAt method and does not display any row on my UITableView.
I do not know what happens there and why this happens.
Have you met such problem and could you please help me to fix it?
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let fetchedResultsController = self.fetchedResultsController, let fetchedObjects = fetchedResultsController.fetchedObjects {
if !searchController.isActive {
print("numberOfRowsInSection fetchedObjects.count - \(fetchedObjects.count)")
return fetchedObjects.count
} else {
if let results = filteredResult[searchController.searchBar.selectedScopeButtonIndex] {
print("numberOfRowsInSection results.count - \(results.count)")
return results.count
}
}
}
print("numberOfRowsInSection - 0")
return 0
}
override func numberOfSections(in tableView: UITableView) -> Int {
if let frc = fetchedResultsController, frc.fetchedObjects?.count != 0 {
print("numberOfSections - 1")
return 1
} else {
print("numberOfSections - 0")
return 0
}
}
What is probably happening is that your cell has height 0. When this happens, cellForRowAt won't be called at all, even if the other methods return a non zero section/row count.
My guess as to why this is happening is that you may be using auto layout for your cell, but your constraints don't allow the cell to figure out its own height. You may be using auto layout unknowingly, since on iOS 11, it's now the default. If you are using storyboards you can set the height for the cell prototype on the attributes inspector, instead of checking the automatic box. Alternatively, you can set it in code with tableView.rowHeight or by implementing func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
Related
I have a UITableView in a UIViewController nested in a UITabBarController that has multiple sections, each with a custom section header that is a subclass of a UIView. The UItableView has all the proper delegates and data sources set up in code and the storyboard.
The footer is explicitly set to 0 in code.
For whatever reason, it seems that the background (in red below) bleeds past each of the UITableViewCells in each section.
My UITableView currently looks like this:
My settings for the tableview in the storyboard looks like this:
and finally, here is the code that controls the tableView, written as extensions on the UITableView subclass:
extension TestViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 64
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 0
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 34
}
}
extension TestViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = TestHeaderView()
view.setLabelWithValues(valueType: "Example", amount: 1)
return view
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath) as! TestTableViewCell
cell.testLabel?.text = "example"
cell.testLabel2?.text = "example"
cell.testLabel3?.text = "example"
return cell
}
}
How do I prevent the background from going past each section of cells?
Figured it out:
Looks like I had to set the footer size to 0 (which then defaults to 1) in the storyboard size inspector column like so:
This will leave a single pixel width of footer, so switch the background color to whatever your cell is.
I need a layout something like in attached image. I have tried adding a subView at the bottom of UICell but it actually distorts the other items UI. Can someone please help? I am working in Xamarin.iOS
One option is to design the cell as the xib.
One option is to use sections and section footers:
override func numberOfSections(in tableView: UITableView) -> Int {
return 5
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
// your spacing
return 20
}
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footer = UIView()
footer.backgroundColor = .clear
footer.isOpaque = false
return footer
}
I have next code when I tap to show / hide content.
func showHideAssets() {
isOpenHiddenAssets = !isOpenHiddenAssets
tableView.beginUpdates()
tableView.reloadSections(IndexSet(integer: 1), with: .fade)
tableView.endUpdates()
}
When first section contain many items, after reloading sections table scrolling to bottom with incorrect offset
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return 10
}
return isOpenHiddenAssets ? assetsHiddenItems.count : 0
}
Video where first section have 3 items. It works well
video 1
Video where first section have 10 items. It have bug.video 2
The solution is replacing
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
with
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat
I am trying to retrieve the values of wInstockArray in a table view cell. Currently the the wInstockArray is empty I am inserting a string on a button click and appending in array. but when I retried the values in cellForRowAtIndexath method it gives error
Index out of range
What I have defined is :
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return wInstockArray.count + 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let firstCell = firstTableView.dequeueReusableCell(withIdentifier: "firstCell")! as UITableViewCell
if wInstockArray.count == 0 {
print("no widgets in instock")
} else {
firstCell.textLabel?.text = wInstockArray[indexPath.row]
print("\(wInstockArray.count)") //prints 1
return firstCell
}
}
inside button click action
wInstockArray.append(item)
Inside button click method, please reload your table.
YOUR_TABLE.reloadData()
and update this method,
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return wInstockArray.count
}
In numberOfRowsInSection method return wInstockArray array count
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return wInstockArray.count
}
Inside the button click action, reload the tableView
wInstockArray.append(item)
tableView.reloadData()
Whenever I run the app, the tableView has no data, waiting for user to input. The problem is that if the numberOfSections is 1, it works just fine, but when I change it to 2 it crashes because Index out of range
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "expenseCell") as? ExpenseCell else { return UITableViewCell() }
let budget = userBudget[indexPath.section][indexPath.row]
cell.delegate = self
cell.configureCell(budget: budget)
return cell
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle.none
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return userBudget[section].count // <- Crash here
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Practice with Sections \(section)"
}
It is because you are accessing index 1 of userBudget while i assume it contains 0 index only.
This crash happens cause your array userBudget, don't has two elements at the moment you try access his second position.
You must guard that userBudget has two elements on minimium...
You should that you must to assign value to userBudget on your ViewDidLoad.
You are saying that you will have two section to your tableView's delegate, but you have an array which contains only one array. Basically when you try to reach userBadget[1] in your numberOfRowsInSection function and it crashes because it doesn't exist.
Replace
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
With
func numberOfSections(in tableView: UITableView) -> Int {
return userBudget.count
}