0

I have a custom UITableViewHeaderFooterView header.I took the extension on this article Swift - Parallax Header View - ScrollView overlap cells.

import UIKit

class CustomSoccerHeaderView: UITableViewHeaderFooterView {

    var clickBravisso: Soccer?
    @IBOutlet weak var bravoBtn: UIButton!
    @IBOutlet weak var countBravo: UILabel!
   @IBOutlet weak var nameHeader: UILabel!
    @IBOutlet weak var imageHeader: UIImageView!
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code



    }


extension UITableView {

    func addImageHeaderView(headerView: UIView, height: CGFloat) {
        self.contentInset = UIEdgeInsets(top: height, left: 0, bottom: 0, right: 0)
        self.contentOffset = CGPoint(x: 0, y: -height)
        self.tableHeaderView = headerView
        self.tableHeaderView?.frame = CGRect(x: 0, y: 0, width: self.bounds.width, height: height)
    }

    func updateHeaderView(height kTableHeaderHeight: CGFloat) {

        var headerRect = CGRect(x: 0, y: -kTableHeaderHeight , width: self.bounds.width, height: kTableHeaderHeight)
        if self.contentOffset.y < -kTableHeaderHeight {
            headerRect.origin.y = self.contentOffset.y
            headerRect.size.height = -self.contentOffset.y
        }
        self.tableHeaderView?.frame = headerRect
    }

}

In the method of down loading data to the cell header.Stalled in the function to implement Parallax effect.I will be very grateful who will be able to prompt and correct me.Experience in this is not enough and can't find the article right.

func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {

        let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: "CustomSoccerHeaderView") as! CustomSoccerHeaderView

        header.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 350)

        header.clickBravisso = detailSoccer

        header.nameHeader.text = detailSoccer.matchS
        header.countBravo.text = ""


        // header.bravoBtn.addTarget(CustomSoccerHeaderView(), action: #selector(CustomSoccerHeaderView.likeBtn(_:)), for: UIControlEvents.touchUpInside)


        detailSoccer.imagePrS.getDataInBackground { (data, error) in
            header.imageHeader.image = error == nil ? UIImage(data: data!) : nil
        }


        return header
    }

    class DetailSoccerTableViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,UIScrollViewDelegate  {

    @IBOutlet weak var tableView: UITableView!

        var detailSoccer: Soccer!
        var selectedSoccer = [Soccer]()

        var headerView: UIView!

    override func viewDidLoad() {
            super.viewDidLoad()

            let backButton = UIBarButtonItem()
            backButton.title = ""

           self.navigationController?.navigationBar.topItem?.backBarButtonItem = backButton

           // self.navigationItem.rightBarButtonItem = barButton
          //  self.navigationItem.rightBarButtonItem?.tintColor = UIColor.universalColorYellow
            let yourBackImage = UIImage(named: "backItem")
            self.navigationController?.navigationBar.backIndicatorImage = yourBackImage
            self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = yourBackImage
            self.navigationController?.navigationItem.leftItemsSupplementBackButton = true
            self.navigationController?.navigationBar.tintColor = UIColor.universalColorYellow


            //title = detailSoccer.detailTitleS

            let nib: UINib = UINib(nibName: "CustomSoccerHeaderView", bundle: nil)
            tableView.register(nib, forHeaderFooterViewReuseIdentifier: "CustomSoccerHeaderView")


            tableView.tableFooterView = UIView(frame: .zero)

            //tableView.layer.masksToBounds = true
            tableView.estimatedRowHeight = 280
            tableView.rowHeight = UITableView.automaticDimension
            tableView.separatorStyle = .none
            tableView.delegate = self
            tableView.dataSource = self
            tableView.register(UINib(nibName:"FootTableViewCell",bundle:nil), forCellReuseIdentifier: "cellSoc")
            self.view.addSubview(tableView)

            self.edgesForExtendedLayout = UIRectEdge.init(rawValue: 0)
            self.extendedLayoutIncludesOpaqueBars = true

            tableView.addImageHeaderView(headerView: headerView, height: 0)// error 

            tableView.reloadData()
            loadMatchSoccer()

            tableView.rowHeight = UITableView.automaticDimension

        }
 func scrollViewDidScroll(_ scrollView: UIScrollView) {
        tableView.updateHeaderView(height: 200)
    }

        }

this line gives an error - tableView.addImageHeaderView(headerView: headerView, height: 0) headerView = (UIView?) nil

Sandero
  • 11
  • 7
  • and how do you know that headerView is initialised? – Lu_ Jul 08 '19 at 11:39
  • Are you expecting `headerView` to be an instance of `CustomSoccerHeaderView` when you call `tableView.addImageHeaderView(headerView: headerView, height: 0)`? – Chris Jul 08 '19 at 11:40
  • A `UITableView`s `.tableHeaderView` property applies to the table as a whole. Custom views registered via `tableView.register(:forCellReuseIdentifier:)` and `tableView.register(:forHeaderFooterViewReuseIdentifier:)` are for a similar, but separate concept. – Chris Jul 08 '19 at 11:47

2 Answers2

0

You have not initialized headerView

Before adding this line

tableView.addImageHeaderView(headerView: headerView, height: 0)

do add one more line to init headerView.

headerView = UIView(frame: CGRect(x: 0, y: 0, width: self.bounds.width, height: height))

add your code in viewDidLoad will finally look like this

headerView = UIView(frame: CGRect(x: 0, y: 0, width: self.bounds.width, height: height))
tableView.addImageHeaderView(headerView: headerView, height: 0)
Abu Ul Hassan
  • 1,340
  • 11
  • 28
  • Where do I call or take height? – Sandero Jul 08 '19 at 11:56
  • you can 0 or what ever number you want. – Abu Ul Hassan Jul 08 '19 at 12:13
  • Okay I will try thank you.Be if that in touch if you suddenly do not get to implement.I was referring to in the line to indicate the height of the UIView – Sandero Jul 08 '19 at 12:16
  • problem UIView(frame: CGRect(x: 0, y: 0, width: self.bounds.width, height: height)) . In Section height and self.bounds.width. .Changed to zero all does not work, put on UIScreen.main.bounds.width and height 350 to load the application this way works, but for some reason the header does not reach up to the top, a distance of about 200-300 – Sandero Jul 08 '19 at 12:44
  • to be very honest you are not adding header with proper way, you asked to the reason for nil now for next you have to update your question or you need to ask another question – Abu Ul Hassan Jul 08 '19 at 12:53
  • for your ease try changing top value in this statement self.contentInset = UIEdgeInsets(top: height, left: 0, bottom: 0, right: 0) – Abu Ul Hassan Jul 08 '19 at 12:56
  • Also if answer solved the problem you have asked then you should accept answer to it can help other to find right solution. happy coding – Abu Ul Hassan Jul 08 '19 at 12:58
  • Yes, You helped me, but there's a weight and height bug in the code. – Sandero Jul 08 '19 at 12:58
  • I Suggested you to update question or ask a new question for that otherwise it will lead others to miss understand the problem. – Abu Ul Hassan Jul 08 '19 at 12:59
0

If your custom view is defined in a xib, try changing this line:

var headerView: UIView!

To this:

lazy var headerView: CustomSoccerHeaderView = {
    return Bundle.main.loadNibNamed("CustomSoccerHeaderView", owner: nil, options: nil)!.first as! CustomSoccerHeaderView
}()

Be careful not to become confused by the two concepts:

  1. UITableViewHeaderFooterView - has specific child views into which you should put your customisations, ideally should be registered with an identifier.
  2. tableHeaderView - is just any old UIView subclass, does not participate in the cell reuse mechanism.

As described, you need the second option, but your posted code seems to be doing work to support the first option.

Chris
  • 3,445
  • 3
  • 22
  • 28
  • Cast from 'UIViewController' to unrelated type 'CustomSoccerHeaderView' always fails.Gives an error like this.What is the name of the control must be specified in UIStoryboard ? where uiNib or controller class tableview? – Sandero Jul 08 '19 at 12:11
  • My mistake. Loading from storyboard does return a `UIViewController`, but you need a way of loading a `UIView`. Is your custom view in a `.xib` or a Storyboard? – Chris Jul 08 '19 at 13:15
  • xib file I pointed out all the questions .I have custom xib Tableviewcell View section header – Sandero Jul 08 '19 at 13:18
  • I've changed my answer to load a view from a xib and link to the relevant docs. – Chris Jul 08 '19 at 14:07