Search code examples
iosswiftuitableviewsections

Remove header and corresponding cells from UI in UITableView


How can the header and the whole section be removed from TableView "Edit" UI? I know that it is possible to do so in code with tableView.deleteSections(), but I need the user to be able to do this when he taps the "Edit" button.

Here is the explanation:

image.

I'm using Swift 2.


Solution

  • Let's start by defining custom subclass of UITableViewHeaderFooterView. This class will be used to display headers in out table view.

    class HeaderView : UITableViewHeaderFooterView {
    
        var actionHandlerBlock: (Void -> Void)?;
    
        override init(reuseIdentifier: String?) {
    
            super.init(reuseIdentifier: reuseIdentifier)
    
            let button = HeaderView.SetupButton()
            addSubview(button);
        }
    
        required init?(coder aDecoder: NSCoder) {
    
            super.init(coder: aDecoder)
    
            let button = HeaderView.SetupButton()
            addSubview(button);
        }
    
        func removeButtonTapped(sender: AnyObject) {
            actionHandlerBlock?();
        }
    
    }
    
    private extension HeaderView {
    
        static func SetupButton() -> UIButton {
            let button = UIButton.init();
            button.addTarget(self, action: "removeButtonTapped:", forControlEvents: .TouchUpInside)
            button.setTitleColor(UIColor.redColor(), forState: .Normal)
            button.setTitle("Remove section", forState: .Normal)
            button.sizeToFit()
            return button
        }
    
    }
    

    This class is really simple. It's responsibility is to create header view with one additional view - button that will be used by us to detect when user wants to remove section of the table view.

    Block actionHandlerBlock is called every time user taps button in our header view.

    In order to remove section after user taps button in our header view we have to provide some custom logic to the delegate of table view.

    override func viewDidLoad() {
        super.viewDidLoad()
    
        tableView.registerClass(HeaderView.self, forHeaderFooterViewReuseIdentifier: "header")
    
        //rest of your set up code here
    }
    
    func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let header = tableView.dequeueReusableHeaderFooterViewWithIdentifier("header") as! HeaderView
        header.actionHandlerBlock = { [section] in
            //don't forget to remove section from your data source here
            tableView.deleteSections(NSIndexSet(index: section), withRowAnimation: .None)
        }
    
        return header
    }
    
    func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 50
    }
    

    In function tableView:viewForHeaderInSection: we set actionHandlerBlock property of the header view. We simply remove section each time this block is called. Remember to modify data source of your table view before you call deleteSections: method - your data source has to know about the removal of the section to be able to return correct number of sections in numberOfSectionsInTableView: function of your data source.