I had a custom cell being used as a tableview section header. I updated to swift 3 and now it is not showing anymore
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = tableView.dequeueReusableCell(withIdentifier: "tableHeader") as! tableHeader
then i put in some constraints and return header
Your custom class should extend from UITableViewHeaderFooterView and it will work.
I know it's a late answer but for some who did not find the correct answer till. You can use UITableViewSectionHeight. Below is an example:
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 80 // this is your row height
}
Related
Using method below of viewForHeaderInSection i try and display an image in table header section one , but i also want a heading text, using the method of heading title text i am able to display the heading for all sections but not section 1 , do i need to make some changes to heading view for section one to be able to display the heading , if i were to remove the viewForHeaderInSection then the title for first header section also shows up
let sectionTitle = ["Feedback", "Follow Us"]
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if section == 0 {
headerTop.headerLogo.image = UIImage(named: "foodpin-logo")
return headerTop.topView
}
return nil
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sectionTitle[section]
}
You need to create a text label in your headerTop view and remove this function override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int). So your code will be like this:
let sectionTitle = ["Feedback", "Follow Us"]
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
headerTop.headerLogo.image = (section == 0) ? UIImage(named: "foodpin-logo") : nil
headerTop.yourHeaderTextLabel.text = sectionTitle[section]
return headerTop.topView
}
It seems like you are looking for tableHeaderView! The issue is you are overriding the first section's header.
You may consider setting the tableView's tableHeaderView for the headerTop instead. So all sections will have their titles as you expected.
tableView. tableHeaderView = headerTop
Also, if you want yout table's header to be sticky, there are bunch of tutorials for that.
I need an advice with ViewContoller's scheme. I should create a view with Billing addresses. There can be no address at all, or some addresses. If there no one, there should be only a button "Add New". And if there are addresses, each should have buttons Edit, Remove, and "Add New" too.
I have data for this VC as JSON, parsed and saved to plist.
So what is logic to make this View looks different depends on 1) if there are addresses or not? and 2) if there 1, or 2, or maybe 20 billing addresses?
Thanks a lot!
I solved issues like this with UITableVIew and the UITableViewDataSource and UITableViewDelegate:
setup the table view for one section (adresses)
func numberOfSections(in tableView: UITableView) -> Int {return 1;}
return the address arrays length in the delegate method
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
return adresses.count
}
set the view for footer if the arrays length is 0
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
if adresses.count == 0 {
let vw = YourViewClass()
//I use blockskit library here (vw.bk_) to recognize a tap, but you can add a button by yourself
vw.bk_(whenTapped: {
//Create and present your next viewcontroller to
})
return vw
}
return nil
}
set the footers height to 0 if there are addresses
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
if addresses.count > 0 {
return YOUR_DESIRED_FOOTER_HEIGHT_FOR_INPUT
}
return 0
}
create row for each address
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let address = addresses[indexPath.row]
let tableViewCell = UITableViewCell() //maybe you have to create your own if the layout does not fit
//set tableViewCell's title / description to show address values
return tableViewCell
}
In this case, the footer view (you can do the same in the header if you want) with the add button is shown when no addresses are available, and it is hidden, when addresses are available.
I am developing an application in Swift3 where I have to show and hide UITableView Header for different users. For displaying UITableView Header View, I have created a custom class CustomHeaderCell of UITableViewCell.
Here is my code:
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 235.0
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell") as! CustomHeaderCell
return headerCell
}
Now Can anyone please help me to hide this Header of my UITableView?
Note: I tried using this tableView.tableHeaderView?.isHidden = true, but not working. Should I need to do the validation in heightForHeaderInSection?
Reference Link to Add HeaderViewCell: http://www.accella.net/knowledgebase/custom-header-and-footer-views-for-uitableviews/
If you have a way to differentiate users then you can just change the header height like this
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
if userA {
return 235.0
} else {
return 0
}
}
That should help in hiding the header
You are mixing tableHeaderView and section header views, which are differents:
tableHeaderView is a view showed as a header for the whole UITableView
section header views are reusable views used for displaying header above each section
In your case, you want to use section header views, so you should return empty ones for non concerned users (I assume here sectionNeedHeader will be replaced by your condition).
Also, you better use UITableViewHeaderFooterView instead of UITableViewCell. The behavior is globally the same but it's made for this usage:
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
if sectionNeedHeader {
return 235.0
}
return 0.0
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if sectionNeedHeader {
let headerCell = tableView.dequeueReusableHeaderFooterView(withIdentifier: "HeaderView") as! CustomHeaderView
return headerView
}
return nil
}
In iOS 11, my section headers always appear, regardless of whether the items are 0 or more.
On iOS 10 devices, my code works and sections disappear when item count is 0. But on iOS 11, the same code has no affect.
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if sections[section].items.count > 0{
return sections[section].title
}else{
return nil
}
}
In iOS 11 if you implement only titleForHeaderInSection and return nil, you will not see a header view. But if you also implement viewForHeaderInSection, regardless of what you return, there will be a section.
This alone will not show a section header:
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return nil
}
This will show a section header with no title:
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return nil
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return nil
}
So both methods may return nil and the header will be visible. If only titleForHeaderInSection is implemented, no header shows up. That does seem to be a case only in iOS 11. Not sure if it's a bug or a way to force developers chose one method of the two. But the docs confirm this behaviour about titleForHeaderInSection:
"Return Value: A string to use as the title of the section header. If you return nil , the section will have no title."
So nothing about showing or not showing, this method only returns the string for the title. Which makes sense. But what does look like a bug is that returning nil in viewForHeaderInSection will show the section header.
To hide a section header for, say, section 0, implement the following method like so:
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
if (section == 0) {
return CGFloat.leastNormalMagnitude //Now section 0's header is hidden regardless of the new behaviour in iOS11.
}
return tableView.sectionHeaderHeight
}
This solution also works for grouped UITableViews, as discussed below.
Update: If you execute reloadSections(..), this solution causes an
NSException of type 'CALayerInvalidGeometry'
If you return 0 in the if statement however, this crash doesn't occur! :)
Therefore, I would say the best solution I have found (atleast for plain UITableViews) is:
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
if (section == 0) {
return 0
}
return tableView.sectionHeaderHeight
}
Implement tableView(_:heightForHeaderInSection:) to return UITableViewAutomaticDimension.
This will suppress the section header in exactly the case where titleForHeaderInSection returns nil (and otherwise it will use the default header height from the table).
If you explicitly tell iOS 11 to use a height of 0 in heightForHeaderInSection it will hide the section header. You can still use automatic header sizing by returning UITableViewAutomaticDimension for non-zero height headers. Here's an example of a solution to workaround the iOS 11 bug:
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
guard shouldShowSectionHeader(section: section) else { return 0 }
return UITableViewAutomaticDimension
}
You'll need to implement shouldShowSectionHeader to determine whether or not to show the section header.
iOS 11.3, works in production
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return sections[section].headerViewModel?.makeView(bindImmediately: true)
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return sections[section].headerViewModel == nil ? 0 : UITableViewAutomaticDimension
}
return empty view from viewForHeaderInSection
swift 3, 4 and 4.2
To hide your tableView header
tableView.tableHeaderView?.frame = CGRect.zero
and to show it back
tableView.tableHeaderView?.frame = CGRect(x: 0, y: 0, width: tableView.frame.width, height: 66)
What worked for me:
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 0.01
}
Coding in Swift 3. Have a tableView with custom cells and header.
I have a tableView with custom cells and headers. The headers have two (2) labels in them and have dynamic cell heights since the labels may be long. My problem is the first time the tableView and sections are configured the label appears as it should, HOWEVER, after scrolling down and then back up the headers' layout somehow breaks.
As you can see below, after I scroll down then back up to the cells, the label is getting cutoff.
After printing out what methods are being called I found that the first time scrolling down the tableView the following two (2) override functions are called.
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
print("\(section) heightForHeaderInSection")
print("\(section) returning AUTO for header")
return UITableViewAutomaticDimension
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
print("\(section) viewForHeaderInSection")
let header = tableView.dequeueReusableCell(withIdentifier: "QuestionHeader") as! QuestionHeader
header.delegate = self
header.contentView.backgroundColor = UIColor.groupTableViewBackground
header.questionTextLabel.text = String(questionStringArray[section])
header.questionNumberLabel.text = (String(section + 1) + ")")
return header.contentView
}
But when i scroll back up ONLY the viewForHeader function is called and I think because the height is no longer being set to UITableViewAutomaticDimension the labels get cutoff?
Any ideas?
You should return header instead of header.contentView from tableView: viewForHeaderInSection: method:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = tableView.dequeueReusableCell(...
...
return header
}