so I currently have a TableViewController that has headerview and prototype cells. Inside the headerview, there is an image. I have programmed it to where a user scrolls down, the headerview stretches down. But I want to find a way to make that header view stick where it is at and when a user scrolls up on the table view, the cells go over the headerview instead of the headerview scrolling up with the cells which it currently is doing. Here is my code for the TableViewController:
import UIKit
class HeaderViewTableViewController: UITableViewController {
var image: UIImageView?
var image2: UIImageView?
var songNameArray = ["Intro", "The Box", "Start wit Me (feat. Gunna)", "Perfect Time", "Moonwalkin (feat. Lil Durk)", "Big Stepper", "Gods Eyes", "Peta (feat. Meek Mill)", "Boom Boom Boom", "Elyse's Skit", "High Fashion (feat. Mustard)", "Bacc Seat (feat. Ty Dolla $ign)", "Roll Dice", "Prayers to the Trap God", "Tip Toe (feat. A Boogie wi da Hoodie)", "War Baby"]
private let tableHeaderViewHeight: CGFloat = 350.0
private let tableHeaderViewCutAway: CGFloat = 0.1
var headerView: HeaderView!
var headerMaskLayer: CAShapeLayer!
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = UIView()
headerView = tableView.tableHeaderView as! HeaderView
headerView.imageView = image
tableView.tableHeaderView = nil
tableView.addSubview(headerView)
tableView.contentInset = UIEdgeInsets(top: tableHeaderViewHeight, left: 0, bottom: 0, right: 0)
tableView.contentOffset = CGPoint(x: 0, y: -tableHeaderViewHeight + 64)
//cut away header view
headerMaskLayer = CAShapeLayer()
headerMaskLayer.fillColor = UIColor.black.cgColor
headerView.layer.mask = headerMaskLayer
let effectiveHeight = tableHeaderViewHeight - tableHeaderViewCutAway/2
tableView.contentInset = UIEdgeInsets(top: effectiveHeight, left: 0, bottom: 0, right: 0)
tableView.contentOffset = CGPoint(x: 0, y: -effectiveHeight)
updateHeaderView()
}
func updateHeaderView() {
let effectiveHeight = tableHeaderViewHeight - tableHeaderViewCutAway/2
var headerRect = CGRect(x: 0, y: -effectiveHeight, width: tableView.bounds.width, height: tableHeaderViewHeight)
if tableView.contentOffset.y < -effectiveHeight {
headerRect.origin.y = tableView.contentOffset.y
headerRect.size.height = -tableView.contentOffset.y + tableHeaderViewCutAway/2
}
headerView.frame = headerRect
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y:0))
path.addLine(to: CGPoint(x: headerRect.width, y: 0))
path.addLine(to: CGPoint(x: headerRect.width, y: headerRect.height))
path.addLine(to: CGPoint(x: 0, y: headerRect.height - tableHeaderViewCutAway))
headerMaskLayer?.path = path.cgPath
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
self.tableView.decelerationRate = UIScrollView.DecelerationRate.fast
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return UITableView.automaticDimension
}
#IBAction func backButton(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
}
extension HeaderViewTableViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return songNameArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SongCell", for: indexPath) as! SongNameTableViewCell
cell.songName.text = songNameArray[indexPath.row]
return cell
}
}
extension HeaderViewTableViewController {
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
updateHeaderView()
}
}
Any idea on how to achieve this? Also I have a button nested inside the headerview that I would like to stick to the top of the view controller when users scroll up. I have it nested there because I'm not sure where else it could go in a table view like a custom cell.
Heres an image of how it is setup in my storyboard and what it looks like when ran on the simulator.
Related
I am trying to draw a custom shape in the headerView for a given section in my UITableviewController. Here is my code:
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
10
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = UIView()
view.backgroundColor = .white
let rect = view.bounds
let bezier = UIBezierPath()
bezier.move(to: CGPoint(x: rect.minX, y: rect.midY))
bezier.addLine(to: CGPoint(x: rect.maxX, y: rect.midY))
bezier.stroke()
let shape = CAShapeLayer()
shape.path = bezier.cgPath
shape.strokeColor = UIColor.red.cgColor
view.layer.addSublayer(shape)
return view
}
The UIView is rendered correctly. I know this because I can see the color of the header sections change from the default color to white. However, the drawing I have done in the CAShapeLayer is not being rendered. I am thinking possibly there is configuration missing in the layer instantiation?
This solved my problem:
class ViewWithLine : UIView {
override func draw(_ rect: CGRect) {
let y: CGFloat = rect.midY
let x1: CGFloat = rect.minX + 5
let x2: CGFloat = rect.maxX - 5
UIColor.lightGray.setStroke()
let b = UIBezierPath()
b.lineWidth = 0.5
b.move(to: CGPoint(x: x1, y: y))
b.addLine(to: CGPoint(x: x2, y: y))
b.stroke()
}
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
5
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = ViewWithLine()
view.backgroundColor = .white
return view
}
could somebody help me?
I have Collection view with insets, Scroll Direction Horizontal, Paging enables and no space between cells. And the issue is that the paging doesn't stop on each cell.
I tried all possible solution which I can find on StackOverflow and the World Wide Web but nothing works. I use Xcode 10 and Swift5 and this is for an iPhone app. I don't add my collectionviewcell code because it have only the IBoutlet for the Label.
class ViewController: UIViewController, UICollectionViewDataSource,
UICollectionViewDelegate {
#IBOutlet weak var collectionView: UICollectionView!
private let item = ["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday", "Sunday"]
private let cellScaling: CGFloat = 0.33
private var cellWidth: CGFloat = 0
override func viewDidLoad() {
super.viewDidLoad()
UpdateUI()
}
func UpdateUI(){
self.collectionView.backgroundColor = UIColor.white
let screenSize = UIScreen.main.bounds.size
let cellWidth = floor(screenSize.width * cellScaling)
let insetX = (view.bounds.width - cellWidth) / 2
let layout = collectionView!.collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSize(width: cellWidth, height: collectionView.bounds.height)
collectionView.contentInset = UIEdgeInsets(top: 0, left: insetX, bottom: 0, right: insetX)
// layout.minimumLineSpacing = 0
self.cellWidth = cellWidth
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.item.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
cell.label.text = self.item[indexPath.row]
cell.backgroundColor = UIColor.cyan
return cell
}
private var startingScrollingOffset = CGPoint.zero
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
startingScrollingOffset = scrollView.contentOffset
}
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let page: CGFloat
let offset = scrollView.contentOffset.x + scrollView.contentInset.left
let proposedPage = offset / max(1, cellWidth)
let snapPoint: CGFloat = 0.1
let snapDelta: CGFloat = offset > startingScrollingOffset.x ? (1-snapPoint) : snapPoint
if floor(proposedPage + snapDelta) == floor(proposedPage){
page = floor(proposedPage)
} else {
page = floor(proposedPage + 1)
}
targetContentOffset.pointee = CGPoint(x: cellWidth * page, y: targetContentOffset.pointee.y)
}
}
enter image description here
And please Notice that I tried all other solution what I could find. Before you vote to delete this Question. the photo shows what it should look like on every cell.
I had to do a similar collection view a few months ago,
This is the code that I use:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let layout = theNameOfYourCollectionView.collectionViewLayout as! UICollectionViewFlowLayout
let cellWidthIncludingSpacing = layout.itemSize.width + layout.minimumLineSpacing // Calculate cell size
let offset = scrollView.contentOffset.x
let index = (offset + scrollView.contentInset.left) / cellWidthIncludingSpacing // Calculate the cell need to be center
if velocity.x > 0 { // Scroll to -->
targetContentOffset.pointee = CGPoint(x: ceil(index) * cellWidthIncludingSpacing - scrollView.contentInset.right, y: -scrollView.contentInset.top)
} else if velocity.x < 0 { // Scroll to <---
targetContentOffset.pointee = CGPoint(x: floor(index) * cellWidthIncludingSpacing - scrollView.contentInset.left, y: -scrollView.contentInset.top)
} else if velocity.x == 0 { // No dragging
targetContentOffset.pointee = CGPoint(x: round(index) * cellWidthIncludingSpacing - scrollView.contentInset.left, y: -scrollView.contentInset.top)
}
}
This code calculates the size of your cell, how many cells have already been shown and once the scroll is finished, adjust it to leave the cell centered.
Make sure you have the pagingEnabled of your collectionView in false if you want to use this code.
I hope I help you!
I am trying to achieve a UITableView drop down when I click on a button. Initially the tableView should be hidden, and when user presses button, it should drop down. I have been trying to achieve this with a UIStackView but to no success. Maybe I am doing it wrong or maybe there is another approach do do this.
let stackView = UIStackView()
var btn: UIButton!
var myTableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
myTableView.delegate = self
myTableView.dataSource = self
myTableView.tableFooterView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 1))
myTableView.frame = CGRect(x: 0, y: 0, width: 300, height: 200)
myTableView.center = CGPoint(x: self.view.frame.width/2, y: self.view.frame.height/2)
myTableView.showsVerticalScrollIndicator = false
btn = UIButton(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 50))
btn.backgroundColor = UIColor.blue.withAlphaComponent(0.3)
btn.setTitle("DropDownMenu", for: UIControlState.normal)
btn.titleLabel?.textColor = .white
btn.titleLabel?.textAlignment = .center
btn.center = CGPoint(x: self.view.frame.width/2, y: myTableView.center.y - myTableView.frame.height/2 - btn.frame.height/2)
btn.addTarget(self, action: #selector(btnPressed), for: UIControlEvents.touchUpInside)
stackView.axis = UILayoutConstraintAxis.vertical
stackView.distribution = UIStackViewDistribution.equalSpacing
stackView.alignment = UIStackViewAlignment.center
stackView.spacing = 16.0
stackView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(btn)
stackView.addSubview(myTableView)
self.view.addSubview(stackView)
}
#objc func btnPressed() {
UIView.animate(withDuration: 1) {
self.myTableView.isHidden = !self.myTableView.isHidden
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "This is cell " + indexPath.row.description
cell.textLabel?.textColor = .black
return cell
}
I can get the tableView to disappear but with no animations. Any thoughts?
The approach I ended up taking was not going via a UIStackView but insead simply having a button that animates the tableView's frame. The frame is initially set to the width of the screen and a height of 0. When user presses button, I set the height.
UIView.animate(withDuration: 0.25, animations: {
self.menuTable.frame = CGRect(x: 0, y: (sender.center.y + sender.frame.height/2), width: self.view.frame.width, height: yourHeight)
})
I have a table view embedded in an iCarousel item and firstly I can't seem to set the view frame whether it's in viewDidLayoutSubviews() but also when I tap the Tableview all the cells disappear. I have created the Tableview in its own ViewController as each carousel item will need editing buttons for the Tableviews they contain. If I don't put the Tableview in its own view controller the cells remain but I get an index out of range when scrolling a lot of views and I can't add editing buttons. I've run out of ideas and would love some pointers or tips.
class BillSplitterTableView: UIViewController, UITableViewDataSource, UITableViewDelegate {
var splitter: BillSplitter?
var tableView: UITableView!
var viewFrame: CGRect?
init(frame: CGRect, splitter: BillSplitter) {
super.init(nibName: nil, bundle: nil)
self.splitter = splitter
self.viewFrame = frame
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:)")
}
override func viewDidLoad() {
super.viewDidLoad()
let subView = UIView(frame: viewFrame!)
view.backgroundColor = .clear
tableView = UITableView(frame: view.frame)
tableView.delegate = self
tableView.dataSource = self
tableView.frame = subView.frame
tableView.separatorStyle = .none
tableView.estimatedRowHeight = 35
let tableViewBackground = UIImageView(image: UIImage(data: splitter?.image as! Data, scale:1.0))
tableViewBackground.contentMode = .scaleAspectFit
tableViewBackground.frame = tableView.frame
tableView.backgroundView = tableViewBackground
subView.addSubview(tableView)
view.addSubview(subView)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (splitter?.items?.count)! > 0 {
return (splitter!.items?.count)!
} else {
TableViewHelper.EmptyMessage("\(splitter?.name!) has no items to pay for.", tableView: tableView)
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
tableView.register(SplitterCarouselItemTableViewCell.classForCoder(), forCellReuseIdentifier: "splitterCarouselItemTableViewCell")
let cell: SplitterCarouselItemTableViewCell = tableView.dequeueReusableCell(withIdentifier: "splitterCarouselItemTableViewCell") as! SplitterCarouselItemTableViewCell
let item = (splitter?.items?.allObjects as! [Item])[indexPath.row]
let count = item.billSplitters?.count
cell.backgroundColor = UIColor(netHex: 0xe9edef).withAlphaComponent(0.5)
if count! > 1 {
cell.name!.text = "\(item.name!)\nsplit \(count!) ways"
cell.price!.text = "£\(Double(item.price)/Double(count!))"
} else {
cell.name!.text = item.name!
cell.price!.text = "£\(item.price)"
}
return cell
}
}
the carousel viewcontroller:
func numberOfItems(in carousel: iCarousel) -> Int {
return allBillSplitters.count
}
func carousel(_ carousel: iCarousel, viewForItemAt index: Int, reusing view: UIView?) -> UIView {
let splitter = allBillSplitters[index]
carouselIndex = index
let splitterView = SplitterCarouselItemView(frame: CGRect(x: 0, y: 0, width: width, height: height))
let viewWidth = Int(splitterView.frame.width)
let nameLabel = SplitterCarouselItemNameLabel(frame: CGRect(x: 0, y: 0, width: viewWidth, height: 30))
let emailLabel = SplitterCarouselItemEmailLabel(frame: CGRect(x: 0, y: 30, width: viewWidth, height: 20))
let addItemButton = SplitterCarouselItemButton(frame: CGRect(x: viewWidth - 45, y: 50, width: 35, height: 35), addsItem: true)
let deleteItemButton = SplitterCarouselItemButton(frame: CGRect(x: 15, y: 50, width: 35, height: 35), addsItem: false)
let itemHeight = Int(splitterView.frame.height)
let payTotalButton = SplitterCarouselItemPayButton(frame: CGRect(x: 0, y: itemHeight - 35, width: viewWidth + 1, height: 35))
let tableViewHeight = Int(height - 130)
let frame = CGRect(x: 0, y: 85, width: viewWidth, height: tableViewHeight)
let tableView = BillSplitterTableView(frame: frame, splitter: splitter)
splitterView.addSubview(nameLabel)
splitterView.addSubview(emailLabel)
splitterView.addSubview(addItemButton)
splitterView.addSubview(deleteItemButton)
splitterView.addSubview(tableView.view)
splitterView.addSubview(payTotalButton)
nameLabel.text = "\(allBillSplitters[index].name!)"
emailLabel.text = "\(allBillSplitters[index].email!)"
payTotalButton.setTitle("Pay £\(allBillSplitters[index].total)", for: .normal)
return splitterView
}
func carousel(_ carousel: iCarousel, valueFor option: iCarouselOption, withDefault value: CGFloat) -> CGFloat {
if allBillSplitters.count > 2 {
switch option {
case .spacing:
return value * 1.05
case .fadeMin:
return 0.0
case .fadeMinAlpha:
return 0.3
case .fadeMax:
return 0.0
default:
return value
}
}
return value
}
Thanks for any help in advance
We have a portion of our UI which is a small list of labels with color swatches next to them. The design I'm taking over has six of these hard-coded in the layout even though the actual data is dynamic, meaning if we only need to show three, we have to explicitly hide three, which also throws off the balance of the page. Making matters worse is each one of those 'items' is actually made up of several sub-views so a screen with six hard-coded items has eighteen IBOutlets.
What I'm trying to do is to instead use a UITableView to represent this small portion of the screen, and since it won't scroll, I was wondering if you can use AutoLayout to configure the intrinsic content height of the UITableView to be based on the number of rows.
Currently I have a test page with a UITableView vertically constrained to the center, but without a height constraint because I am hoping to have the table's intrinsic content size reflect the visible rows. I have also disabled scrolling on the table. When I reload the table, I call updateConstraints. But the table still does not resize.
Note: We can't use a UIStackView (which would have been perfect for this) because we have to target iOS8 and that wasn't introduced until iOS9, hence this solution.
Has anyone been able to do something similar to our needs?
Ok, so unlike UITextView, it doesn't look like UITableView ever returns an intrinsic size based on the visible rows. But that's not that big a deal to implement via a subclass, especially if there's a single section, no headers or footers, and the rows are of a fixed height.
class AutoSizingUiTableView : UITableView
{
override func intrinsicContentSize() -> CGSize
{
let requiredHeight = rowCount * rowHeight
return CGSize(width: UIView.noIntrinsicMetric, height: CGFloat(requiredHeight))
}
}
I'll leave it up to the reader to figure out how to get their own rowCount. The same if you have variable heights, multiple sections, etc. You just need more logic.
By doing this, it works great with AutoLayout. I just wish it handled this automatically.
// Define this puppy:
class AutoTableView: UITableView {
override func layoutSubviews() {
super.layoutSubviews()
self.invalidateIntrinsicContentSize()
}
override var intrinsicContentSize: CGSize {
get {
var height:CGFloat = 0;
for s in 0..<self.numberOfSections {
let nRowsSection = self.numberOfRows(inSection: s)
for r in 0..<nRowsSection {
height += self.rectForRow(at: IndexPath(row: r, section: s)).size.height;
}
}
return CGSize(width: UIView.noIntrinsicMetric, height: height)
}
set {
}
}
}
and make it your class in IB.
obs: this is if your class is only cells and shit. if it has header, footer or some other thign, dunno. it'll not work. for my purposes it works
peace
This can be done, please see below for a very simple (and rough - rotation does not work properly!) example, which allows you to update the size of the table view by entering a number in the text field and resetting with a button.
import UIKit
class ViewController: UIViewController {
var tableViewController : FlexibleTableViewController!
var textView : UITextView!
var button : UIButton!
var count : Int! {
didSet {
self.refreshDataSource()
}
}
var dataSource : [Int]!
let rowHeight : CGFloat = 50
override func viewDidLoad() {
super.viewDidLoad()
// Configure
self.tableViewController = FlexibleTableViewController(style: UITableViewStyle.plain)
self.count = 10
self.tableViewController.tableView.backgroundColor = UIColor.red
self.textView = UITextView()
self.textView.textAlignment = NSTextAlignment.center
self.textView.textColor = UIColor.white
self.textView.backgroundColor = UIColor.blue
self.button = UIButton()
self.button.setTitle("Reset", for: UIControlState.normal)
self.button.setTitleColor(UIColor.white, for: UIControlState.normal)
self.button.backgroundColor = UIColor.red
self.button.addTarget(self, action: #selector(self.updateTable), for: UIControlEvents.touchUpInside)
self.layoutFrames()
// Assemble
self.view.addSubview(self.tableViewController.tableView)
self.view.addSubview(self.textView)
self.view.addSubview(self.button)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func refreshDataSource() -> Void {
if let _ = self.dataSource {
if !self.dataSource.isEmpty {
self.dataSource.removeAll()
}
}
else
{
self.dataSource = [Int]()
}
for count in 0..<self.count {
self.dataSource.append(count)
}
self.tableViewController.dataSource = self.dataSource
self.tableViewController.tableView.reloadData()
if let _ = self.view {
self.layoutFrames()
self.view.setNeedsDisplay()
}
}
func updateTable() -> Void {
guard let _ = self.textView.text else { return }
guard let validNumber = Int(self.textView.text!) else { return }
self.count = validNumber
}
func layoutFrames() -> Void {
if self.tableViewController.tableView != nil {
self.tableViewController.tableView.frame = CGRect(origin: CGPoint(x: self.view.frame.width / 2 - 100, y: 100), size: CGSize(width: 200, height: CGFloat(self.dataSource.count) * self.rowHeight))
NSLog("\(self.tableViewController.tableView.frame)")
}
if self.textView != nil {
self.textView.frame = CGRect(origin: CGPoint(x: 50, y: 100), size: CGSize(width: 100, height: 100))
}
if self.button != nil {
self.button.frame = CGRect(origin: CGPoint(x: 50, y: 150), size: CGSize(width: 100, height: 100))
}
}
}
class FlexibleTableViewController : UITableViewController {
var dataSource : [Int]!
override init(style: UITableViewStyle) {
super.init(style: style)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.dataSource.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") ?? UITableViewCell()
cell.frame = CGRect(origin: CGPoint(x: 10, y: 5), size: CGSize(width: 180, height : 40))
cell.backgroundColor = UIColor.green
return cell
}
}
Whether it is a good idea or not, is, as has been pointed out, another question! Hope that helps!
Version from no_ripcord accounting for header and footer height
final // until proven otherwise
class IntrinsicallySizedTableView: UITableView {
override func layoutSubviews() {
super.layoutSubviews()
self.invalidateIntrinsicContentSize()
}
override var intrinsicContentSize: CGSize {
guard let dataSource = self.dataSource else {
return super.intrinsicContentSize
}
var height: CGFloat = (tableHeaderView?.intrinsicContentSize.height ?? 0)
+ contentInset.top + contentInset.bottom
if let footer = tableFooterView {
height += footer.intrinsicContentSize.height
}
let nsections = dataSource.numberOfSections?(in: self) ?? self.numberOfSections
for section in 0..<nsections {
let sectionheader = rectForHeader(inSection: section)
height += sectionheader.height
let sectionfooter = rectForFooter(inSection: section)
height += sectionfooter.height
let nRowsSection = self.numberOfRows(inSection: section)
for row in 0..<nRowsSection {
height += self.rectForRow(at: IndexPath(row: row, section: section)).size.height
}
}
return CGSize(width: UIView.noIntrinsicMetric, height: height)
}
}