为 UITableView Footer Swft 设置约束

Setting constraints to UITableView Footer Swft

我试图用 UIButton 放置页脚,现在我只用 frame 放置它,当我在 apple 的 iphones 上尝试它时,按钮没有放置好,因为我没有设置任何自动布局,问题是我试图将自动布局设置为页脚,但它一直失败,我也不确定是否可以这样做,希望得到方便的帮助,甚至是提示:)。 这是我的 tableView 代码:

import UIKit
import PanModal

protocol FilterTableViewDelegate {
    func didUpdateSelectedDate(_ date: Date)
}

class FilterTableViewController: UITableViewController, PanModalPresentable {
    
    var panScrollable: UIScrollView? {
        return tableView
    }
    
    
    var albumsPickerIndexPath: IndexPath? //  indexPath of the currently shown albums picker in tableview.
    var delegate: FilterTableViewDelegate?
    
    var datesCell = DatesCell()
    
    
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupTableView()
        //        registerTableViewCells()
        
    }
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        //        tableView.frame = view.bounds
    }
    
    override var preferredStatusBarStyle: UIStatusBarStyle {
        return .lightContent
    }
    
    
    
    // MARK: - View Configurations
    
    func setupTableView() {
        
        
        tableView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
        tableView.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
        tableView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
        tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
        
        
        tableView.separatorStyle = .singleLine
        tableView.isScrollEnabled = false
        tableView.allowsSelection = true
        
        
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = 600
        
        
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
        tableView.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
        
    }
    
    
    
    func indexPathToInsertDatePicker(indexPath: IndexPath) -> IndexPath {
        if let albumsPickerIndexPath = albumsPickerIndexPath, albumsPickerIndexPath.row < indexPath.row {
            return indexPath
        } else {
            return IndexPath(row: indexPath.row + 1, section: indexPath.section)
        }
    }
    
    
    // MARK: - UITableViewDataSource
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // If datePicker is already present, we add one extra cell for that
        if albumsPickerIndexPath != nil {
            return 5 + 1
        } else {
            return 5
        }
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        switch indexPath.row {
        case 0:
            
            let byActivityCell = UINib(nibName: "byActivityCell",bundle: nil)
            self.tableView.register(byActivityCell,forCellReuseIdentifier: "byActivityCell")
            let activityCell = tableView.dequeueReusableCell(withIdentifier: "byActivityCell", for: indexPath) as! byActivityCell
            activityCell.selectionStyle = .none
            
            return activityCell
            
        case 1:
            let byTypeCell = UINib(nibName: "ByType",bundle: nil)
            self.tableView.register(byTypeCell,forCellReuseIdentifier: "byTypeCell")
            let typeCell = tableView.dequeueReusableCell(withIdentifier: "byTypeCell", for: indexPath) as! ByType
            typeCell.selectionStyle = .none
            return typeCell
            
        case 2:
            let byHashtagsCell = UINib(nibName: "ByHashtags",bundle: nil)
            self.tableView.register(byHashtagsCell,forCellReuseIdentifier: "byHashtagsCell")
            let hashtagsCell = tableView.dequeueReusableCell(withIdentifier: "byHashtagsCell", for: indexPath) as! ByHashtags
            hashtagsCell.selectionStyle = .none
            
            return hashtagsCell
            
        case 3:
            let byDatesCell = UINib(nibName: "DatesCell",bundle: nil)
            self.tableView.register(byDatesCell,forCellReuseIdentifier: "byDatesCell")
            let datesCell = tableView.dequeueReusableCell(withIdentifier: "byDatesCell", for: indexPath) as! DatesCell
            datesCell.selectionStyle = .none
            datesCell.datesTableViewCellDelegate = self
            
            return datesCell
            
            
        case 4:
            let byAlbumCell = UINib(nibName: "AlbumCell",bundle: nil)
            self.tableView.register(byAlbumCell,forCellReuseIdentifier: "byAlbumCell")
            let albumCell = tableView.dequeueReusableCell(withIdentifier: "byAlbumCell", for: indexPath) as! AlbumCell
            albumCell.configureCell(choosenAlbum: "Any")
            albumCell.selectionStyle = .none
            
            return albumCell
            
            
            
        case 5:
            let albumPickerCell = UINib(nibName: "AlbumsPickerTableViewCell", bundle: nil)
            self.tableView.register(albumPickerCell, forCellReuseIdentifier: "albumPickerCell")
            let albumsPicker = tableView.dequeueReusableCell(withIdentifier: "albumPickerCell", for: indexPath) as! AlbumsPickerTableViewCell
            
            
            return albumsPicker
            
            
        default:
            return UITableViewCell()
        }
        
    }
    
    
    
    
    
    // MARK: - footer Methods:
    override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        return getfooterView()
    }
    
    func getfooterView() -> UIView
    {
        let footerView = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 400))
        let applyFiltersBtn = UIButton(frame: CGRect(x: 0, y: 0, width: 380, height: 40))
        
        
        applyFiltersBtn.center = footerView.center
        
        applyFiltersBtn.layer.cornerRadius = 12
        applyFiltersBtn.layer.masksToBounds = true
        applyFiltersBtn.setTitle("Apply Filters", for: .normal)
        applyFiltersBtn.backgroundColor = #colorLiteral(red: 0.1957295239, green: 0.6059523225, blue: 0.960457623, alpha: 1)
        
        
        //        doneButton.addTarget(self, action: #selector(hello(sender:)), for: .touchUpInside)
        
        
        
        footerView.addSubview(applyFiltersBtn)
        
        
        return footerView
    }
    
    override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return 10
    }
    
    
    
    
    
    
    // MARK: TableViewDelegate Methods:
    
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: false)
        
        
        tableView.beginUpdates()
        
        // 1 - We Delete the UIPicker when the user "Deselect" thr row.
        if let datePickerIndexPath = albumsPickerIndexPath,   datePickerIndexPath.row - 1 == indexPath.row {
            tableView.deleteRows(at: [datePickerIndexPath], with: .fade)
            self.albumsPickerIndexPath = nil
        } else {
            // 2
            //            if let datePickerIndexPath = albumsPickerIndexPath {
            //                tableView.deleteRows(at: [datePickerIndexPath], with: .fade)
            //            }
            albumsPickerIndexPath = indexPathToInsertDatePicker(indexPath: indexPath)
            tableView.insertRows(at: [albumsPickerIndexPath!], with: .fade)
            tableView.deselectRow(at: indexPath, animated: true)
        }
        
        
        
        tableView.endUpdates()
        
    }
    
    
    override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
        if indexPath.row == 4  {
            return indexPath
        } else {
            return nil
        }
        
        
    }
    
    
}


extension FilterTableViewController: DatesTableViewCellDelegate {
    
    func didButtonFromPressed() {
        print("Button From is Pressed")
        let pickerController = CalendarPickerViewController(
            baseDate: Date(),
            selectedDateChanged: { [weak self] date in
                guard let self = self else { return }
                
                //          self.item.date = date
                //TODO: Pass the date to the DatesCell to update the UIButtons.
                self.delegate?.didUpdateSelectedDate(date)
                
                self.tableView.reloadRows(at: [IndexPath(row: 3, section: 0)], with: .fade)
            })
        
        present(pickerController, animated: true, completion: nil)
        
    }
    
    
    
    func didButtonToPressed() {
        //TODO: Present our custom calendar
        let calendarController = CalendarPickerViewController(
            baseDate: Date(),
            selectedDateChanged: { [weak self] date in
                guard let self = self else { return }
                
                self.tableView.reloadRows(at: [IndexPath(row: 3, section: 0)], with: .fade)
            })
        
        
        
        self.present(calendarController, animated: true, completion: nil)
        
    }
    
    
}

首先,一个提示(基于这个问题和您 post 编辑的其他问题):简化您正在做的事情。当您 post 引用 5 个不同单元格的代码 classes 以及用于处理单元格操作委托、插入和删除等的代码时... but你的问题是关于Section Footer布局的,很难提供帮助。

因此,这是一个简单的 table 视图控制器示例,使用默认单元格 class 和自定义 UITableViewHeaderFooterView 部分页脚:

class MySectionFooterView: UITableViewHeaderFooterView {
    
    let applyFiltersBtn = UIButton()
    
    override init(reuseIdentifier: String?) {
        super.init(reuseIdentifier: reuseIdentifier)
        configureContents()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        configureContents()
    }
    
    func configureContents() {

        applyFiltersBtn.translatesAutoresizingMaskIntoConstraints = false
        applyFiltersBtn.layer.cornerRadius = 12
        applyFiltersBtn.layer.masksToBounds = true
        applyFiltersBtn.setTitle("Apply Filters", for: .normal)
        applyFiltersBtn.backgroundColor = #colorLiteral(red: 0.1957295239, green: 0.6059523225, blue: 0.960457623, alpha: 1)

        contentView.addSubview(applyFiltersBtn)

        let g = contentView.layoutMarginsGuide
        
        NSLayoutConstraint.activate([

            // use layoutMarginsGuide for top and bottom
            applyFiltersBtn.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
            applyFiltersBtn.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),
            
            // inset button 20-pts from layoutMarginsGuide on each side
            applyFiltersBtn.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            applyFiltersBtn.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            
            // make button height 40-pts
            applyFiltersBtn.heightAnchor.constraint(equalToConstant: 40.0),
        ])
        
    }
}

class SectionFooterViewController: UITableViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // register cell class for reuse
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
        
        // register Section Footer class for reuse
        tableView.register(MySectionFooterView.self, forHeaderFooterViewReuseIdentifier: "mySectionFooter")

        tableView.sectionFooterHeight = UITableView.automaticDimension
        tableView.estimatedSectionFooterHeight = 50
    }
    
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 8
    }
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = "\(indexPath)"
        return cell
    }

    override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
        let view = tableView.dequeueReusableHeaderFooterView(withIdentifier:"mySectionFooter") as! MySectionFooterView
        return view
    }
}

要处理点击部分页脚中的按钮,您可以在 viewForFooterInSection 中为它分配一个动作,或者将该动作构建到 MySectionFooterView class 中并使用闭包或协议/委托模式。