I am using the code below to set the uitableview viewForHeaderInSection and then I am trying to update just one textfield in the section header but my reference is nil.
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: "ReusableHeader")
header.timeField.text = String(describing: secondsToHoursMinutesSeconds(seconds: counter))
return header
}
My reference code where header comes back as nil:
let header = self.tableView.headerView(forSection: 0)
header?.setNeedsLayout()
Ok , i'am researching about this thing. func self.tableView.headerView(forSection: ) return only UITableViewHeaderFooterView object. If you want use this func , you need use tableView.dequeueReusableHeaderFooterView(withIdentifier: "ReusableHeader")
public override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?{
let view = tableView.dequeueReusableHeaderFooterView(withIdentifier: "ReusableHeader")
return view
}
Related
i have a table with a variable number of sections. If there are more than one section i want to show show custom Headers, but if there is only one, i don't want a header at all.
My Approach is to use func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? and return nil if i have only one section. But instead of showing no header, i get an empty header. Any ideas?
here is my code
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Orders"
tableView.dataSource = self
tableView.delegate = self
let headerNib = UINib.init(nibName: "SectionHeader", bundle: Bundle.main)
tableView.register(headerNib, forHeaderFooterViewReuseIdentifier: "SectionHeader")
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if(ordersList.count < 2) {return nil}
let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "SectionHeader") as! SectionHeader
headerView.label.text = "\(sectionHeaders[section]) (\(ordersList[section].count))"
headerView.button.setTitle(self.collapsed[section] ? "▶" : "▼", for: .normal)
headerView.onTap = {
self.collapsed[section] = !self.collapsed[section]
headerView.button.rotate(self.collapsed[section] ? CGFloat(-.pi/2.0) : CGFloat(.pi/2.0), duration: 0.1, completion: {
self.tableView.beginUpdates()
self.tableView.reloadSections([section], with: .fade)
self.tableView.endUpdates()
})
}
return headerView
}
use heightForHeaderInSection delegate method also. Make height 0 if condition not satisfy. For Reference -
public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
if(ordersList.count < 2) {return 0.1}
else { return HEIGHT} //custom value of view height
}
You have to use the following methods to achieve the desired result:
func numberOfSections(in tableView: UITableView) -> Int {
if(ordersList.count < 2) {return nil}
return ordersList.count
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if(ordersList.count < 2) {return nil}
//else return some view }
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
if(ordersList.count < 2) {return 0}
return some_height
}
Use tableView.numberOfSections to get the section count. And use this value in tableView(_:viewForHeaderInSection:) to check whether you want return SectionHeader or nil. You need to return nil in case you don't want to show header in a particular section.
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
guard tableView.numberOfSections > 1 else {
return nil
}
let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "SectionHeader") as! SectionHeader
//add rest of the code...
return headerView
}
Implement tableView(_:heightForHeaderInSection:) to return the header height based on the section. Return 0 if you don't want to show header in a section otherwise it will take the default header height.
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return (tableView.numberOfSections > 1) ? 100.0 : 0.0
}
you should override numberOfSections method of tableview. And you should not use dequeueReusableHeaderFooterView for section header view. Section header views should be a custom view.
-- numberOfSections
func numberOfSections(in tableView: UITableView) -> Int {
return sectionCount
}
-- sectionHeaderView
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
// you can store data on a view model
let cellViewModel = viewModel.returnViewModel(index: section)
switch cellViewModel.type {
case .sampleViewModel1:
return UIView() // sampleView1
case .sampleViewModel2:
return UIView() // sampleView2
}
}
I am trying to customize static UITableViewController section header with UITableViewCell.
I could successfully cusomise section header in dynamic tableView by using the below set of code,
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell")
headerCell?.textLabel?.text = "Section \(section + 1)"
headerCell?.textLabel?.textColor = UIColor.blue
return headerCell
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
But, couldn't work for static tableview.
How to customise section header with static tableView
The problem is you should return a UIView, not a UITableViewCell in viewForHeaderInSection method.
Also you should keep an instance of header cell for future use (like modifying its view)
Create a field in your TableViewController like this:
private var headerViewCell: UITableViewCell?
and then in the viewForHeaderInSection do this:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell")
headerCell?.textLabel?.text = "Section \(section + 1)"
headerCell?.textLabel?.textColor = UIColor.blue
self.headerViewCell = headerCell
return headerCell?.contentView
}
I think you should unwrap cell when using dequeueReusableCell.
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell") as! HeaderCell // here header cell is your cell's custom class
headerCell.textLabel.text = "Section \(section + 1)"
headerCell.textLabel.textColor = UIColor.blue
return headerCell
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
I am creating a static tableView. My goal is to have a single view that displays a tableView with 3 rows (get support, send feedback, participation terms), and a header + footer.
Right now, it all works fine EXCEPT the fact that there are two extra separators (one between the header and the first cell and the other between the last cell and the footer) that I cannot seem to get rid of.
Here is my code:
final class viewController: UITableViewController {
private let headerContainer = UIView()
private let footerContainer = UIView()
private let tableData = ["Get Support", "Send Feedback", "Participation Terms"]
override func viewDidLoad() {
super.viewDidLoad()
setupHeaderAndFooter()
setupTableView()
}
func setupHeaderAndFooter() {
/* setup code here (not relevant to this question) */
func setupTableView() {
// reinitializing tableView so that we can change its style to grouped
tableView = UITableView(frame: CGRect.zero, style: .grouped)
tableView.delegate = self
tableView.separatorStyle = .singleLine
}
//MARK: UITableView Methods
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return headerContainer
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 150
}
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
return footerContainer
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 200
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 70
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cell")
cell.textLabel!.text = tableData[indexPath.row]
return cell
}
}
One way to achieve this is don't use default separator provided by UITableView. and place one UILabel or UIView and set its background color to light gray and set its height=1 (As per your requirement), width (full tableview width or as per your requirement) and position at bottom of all you content inside cell, header or footer.
Ok here you go.
The easy trick is actually a one-liner and a self-explanatory:
self.tableView.separatorColor = self.tableView.backgroundColor
AFTER:
I hope this helps!
You have to set clipsToBounds to true on your header view.
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = //Get your header here
header.clipsToBounds = true
return header
}
Before:
After:
I want to freeze a tableView cell on top of screen, so that while scrolling, other cells move but the top cell stays on its place.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath)
cell. //I think it must be here
return cell
Thank you.
Use these methods to create tableview header and add any subviews in it.
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = UIView.init()
header.backgroundColor = UIColor.gray
//Add subviews here
return header
}
try this:
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 65
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = view as! UITableViewHeaderFooterView
header.textLabel?.textColor = UIColor.black
header.textLabel?.text="adadafaf"//ur data
}
I have a dictionary which will be a data source for my tableView.
However, I want to add also other cells that are not the part of the dictionary, which means that they should not be under the section title that comes from dictionary.
To give you a better notion of what I'm trying to achieve I created this exemplary project available here
Here is the ViewController implementation, I tried to keep it as short as possible:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let dict2:Dictionary<String,[String]> = ["SECTION1":["This should be under section", "This should be under section too"]]
var dictKeysSorted:[String] = []
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
dictKeysSorted = dict2.keys.sort()
self.tableView.delegate = self
self.tableView.dataSource = self
// Do any additional setup after loading the view, typically from a nib.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (dict2 as NSDictionary).objectForKey(dictKeysSorted[section])!.count + 1
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return dictKeysSorted[section]
}
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 30.0
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return dictKeysSorted.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: CustomCell = tableView.dequeueReusableCellWithIdentifier("cell") as! CustomCell
if indexPath.row == 0
{
cell.label.text = "This cell should be above section"
}
else
{
cell.label.text = (dict2 as NSDictionary).objectForKey(dictKeysSorted[indexPath.section])![indexPath.row-1] as? String
}
return cell
}
}
This is what I get:
My first idea was to create another record in my dictionary and simply omit it using if-statement in
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String?
But this is not the proper solution since it keeps returning an extra empty section header.
How to make tableView "omits" certain section headers?
Thanks in advance
PS. I found it difficult to name this thread properly, if you have any idea how to name it in a more relevant way, feel free to edit the title of this question.
You can implement the UITableViewDelegate method that returns the height of the header returning 0 for the header that you want to hide:
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
Here is the reference.
As stated in the doc, since iOS5 returning an empty header view or an empty title no longer result in an invisible header.
Please note that this will require you to return the default height for the sections that you want to show.