Search code examples
swiftuitableviewdidselectrowatindexpathexpandable

Expandable Sections UITableView IndexPath SWIFT


Im pretty new to coding, I only know Swift. I have found several tutorials to produce drop down sections in a table. Basically it will represent a TV show, the headers will be the seasons and the drop down list of episodes from each season.

I managed to get this working perfectly for what I want from https://github.com/fawazbabu/Accordion_Menu

This all looks good, however I need to be able to select from the drop down items. I have added didSelectRowAtIndexPath with just a simple print of the rows to start with. When I select a row, section or cell, random index paths are returned, the same row can be pressed a second time and return a different value. I thought this was just something I had added to the issue. So I added didSelectRowAtIndexPath to the original code. This has the same issue.

I assume this is because a UIGestureRecogniser is being used as well as didSelectRowAtIndexPath. But I am not sure what the alternative is.

Could someone tell me where I am going wrong please?

import UIKit
import Foundation


class test: UIViewController, UITableViewDelegate, UITableViewDataSource {


    @IBOutlet var tableView: UITableView!
    var sectionTitleArray : NSMutableArray = NSMutableArray()
    var sectionContentDict : NSMutableDictionary = NSMutableDictionary()
    var arrayForBool : NSMutableArray = NSMutableArray()


    override func awakeFromNib() {
        super.awakeFromNib()

        tableView.delegate = self
        tableView.dataSource = self

        arrayForBool = ["0","0"]
        sectionTitleArray = ["Pool A","Pool B"]
        var tmp1 : NSArray = ["New Zealand","Australia","Bangladesh","Sri Lanka"]
        var string1 = sectionTitleArray .objectAtIndex(0) as? String
        [sectionContentDict .setValue(tmp1, forKey:string1! )]
        var tmp2 : NSArray = ["India","South Africa","UAE","Pakistan"]
        string1 = sectionTitleArray .objectAtIndex(1) as? String
        [sectionContentDict .setValue(tmp2, forKey:string1! )]

        self.tableView.registerNib(UINib(nibName: "CategoryNameTableCell", bundle: NSBundle.mainBundle()), forCellReuseIdentifier: "CategoryNameTableCell")
    }

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return sectionTitleArray.count
    }


    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
        if(arrayForBool .objectAtIndex(section).boolValue == true){
            var tps = sectionTitleArray.objectAtIndex(section) as! String
            var count1 = (sectionContentDict.valueForKey(tps)) as! NSArray
            return count1.count
        }
        return 0;
    }

    func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return "ABC"
    }

    func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {

        return 50
    }

    func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
        return 0
    }

    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        if(arrayForBool .objectAtIndex(indexPath.section).boolValue == true){
            return 50
        }
        return 2;
    }

    func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let cell = self.tableView.dequeueReusableCellWithIdentifier("CategoryNameTableCell") as! CategoryNameTableCell
        cell.downArrow.hidden = false
        cell.backgroundColor = UIColor.blackColor()
        cell.tag = section
        cell.CategoryLabel.text = sectionTitleArray.objectAtIndex(section) as? String
        let cellTapped = UITapGestureRecognizer (target: self, action:"sectionHeaderTapped:")
        cell .addGestureRecognizer(cellTapped)
        return cell
    }
    func sectionHeaderTapped(recognizer: UITapGestureRecognizer) {
        println("Tapping working")
        println(recognizer.view?.tag)
        var indexPath : NSIndexPath = NSIndexPath(forRow: 0, inSection:(recognizer.view?.tag as Int!)!)
        if (indexPath.row == 0) {
            var collapsed = arrayForBool .objectAtIndex(indexPath.section).boolValue
            collapsed       = !collapsed;
            arrayForBool .replaceObjectAtIndex(indexPath.section, withObject: collapsed)
            var range = NSMakeRange(indexPath.section, 1)
            var sectionToReload = NSIndexSet(indexesInRange: range)
            self.tableView .reloadSections(sectionToReload, withRowAnimation:UITableViewRowAnimation.Fade)
            tableView.reloadData()
        }
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
        let cell = self.tableView.dequeueReusableCellWithIdentifier("CategoryNameTableCell") as! CategoryNameTableCell
        var manyCells : Bool = arrayForBool .objectAtIndex(indexPath.section).boolValue
        if (!manyCells) {
        } else {
            var content = sectionContentDict .valueForKey(sectionTitleArray.objectAtIndex(indexPath.section) as! String) as! NSArray
            cell.CategoryLabel.text = content .objectAtIndex(indexPath.row) as? String
            cell.backgroundColor = UIColor( red: 49/255, green: 46/255, blue:47/255, alpha: 1.0 )
        }

        return cell
    }
    func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
        println(indexPath.row)
    }

Solution

  • I don't know why you need sections to do it what you want, you can achieve with normal cells, no need to complicate at all. Just differentiating the parent cells of the child cells is all you need.

    I have a repository in Github that achieve what you want, without using sections neither UITapGestureRecognizer. As soon as possible I'll try to update the project to better performance and more levels of depth in the dropdown.

    You can reach it AccordionMenu , and feel free to post anything you need as issue.

    I hope this help you.