Search code examples
iosuitableviewswiftcellssections

Swift selecting a cell in each section


I have a little problem in selecting multiple cells in swift.

I don't want to let the user select as many cells as he wants, he is only allowed to select three cells (one in each Section). To make it more clear I'll give you some code.

I have three sections:

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 3
}

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

    let headerCell = tableView.dequeueReusableCellWithIdentifier("HeaderCell") as! CustomHeaderCell

    /* let  headerCell = tableView.dequeueReusableCellWithIdentifier("HeaderCell") as CustomHeaderCell */
 //   headerCell.backgroundColor = UIColor.set(#E6E2E1)

    switch (section) {
    case 0:
        headerCell.headerLabel.text = "Bundesliga";
        //return sectionHeaderView
    case 1:
        headerCell.headerLabel.text = "BBVA";
        //return sectionHeaderView
    case 2:
        headerCell.headerLabel.text = "BPL";
        //return sectionHeaderView
    default:
        headerCell.headerLabel.text = "Other";
    }

    return headerCell
}

And I want go give the User for example 5 Clubs to select from in each League. He has to select his favourite Club in each League. I don't want to make something like this:

tableView.allowsMultipleSelection = true

Because I want to allow only one Selection in each Section. How can I limit the user like this?


Solution

  • This should work for you:

    override func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
        let selectedIndexPaths = indexPathsForSelectedRowsInSection(indexPath.section)
    
        if selectedIndexPaths?.count == 1 {
            tableView.deselectRowAtIndexPath(selectedIndexPaths!.first!, animated: true)
        }
    
        return indexPath
    }
    
    func indexPathsForSelectedRowsInSection(section: Int) -> [NSIndexPath]? {
        return (tableView.indexPathsForSelectedRows() as? [NSIndexPath])?.filter({ (indexPath) -> Bool in
            indexPath.section == section
        })
    }
    

    Update for Swift 4.1 - with checkmarks for selected cells

    override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
        // Find any selected row in this section
        if let selectedIndexPath = tableView.indexPathsForSelectedRows?.first(where: {
            $0.section == indexPath.section
        }) {
            // Deselect the row
            tableView.deselectRow(at: selectedIndexPath, animated: false)
            // deselectRow doesn't fire the delegate method so need to
            // unset the checkmark here
            tableView.cellForRow(at: selectedIndexPath)?.accessoryType = .none
        }
        return indexPath
    }
    
    override func tableView(_ tableView: UITableView, willDeselectRowAt indexPath: IndexPath) -> IndexPath? {
        // Prevent deselection of a cell
        return nil
    }
    
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.cellForRow(at: indexPath)?.accessoryType = .checkmark
    }
    

    For the tableView, make sure you set…

    allowsMultipleSelection = true
    

    or Selection: MutlipleSelection in Interface Builder

    and for each cell, set

    selectionStyle = .none
    

    or Selection: None in Interface Builder