Victor --------
Victor --------

Reputation: 512

checkbox button in tableview in Swift

I'm trying to create a checkbox functionality in a tableview . It's a to-do list where if the checkbox is pressed the cell hides and appears as completed in a different section.

Coming from C# this was very straightforward to do but in swift there isn't even a checkbox button to start with :(...

I made it to work by adding a button with two images(checked, unchecked) to a custom prototype cell in IB. Since you can't have the tableView and the in-cell-button declared in the same viewcontroller/class I had to subclass the tableViewCell.

Now, how do I access the checkbox from didSelectRowAtIndexPath ? When I select the cell the event fires but when I press the checkbox button in the same cell nothing fires and I can't hide the cell.

var indexTag = checkBoxImage.tag
//this is what I have in TableViewCell class

@IBAction func checkBoxInCell(sender: UIButton) {

   checkBoxImage.setImage(UIImage(named:"checked"),forState:UIControlState.Normal)

   if isChecked != false {
        isChecked = false
        cellitemcontent.removeAtIndex(indexTag)
        //can't access the cell from here to update the tableview
   } 
   else {
        isChecked = true
        checkBoxImage.setImage(UIImage(named:"unchecked"),forState:UIControlState.Normal)
    }

}

//this is what I have in my FirstViewController that contains the tableview

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{        
     cellitemcontent.removeAtIndex(indexTag)
     tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
     //when I press the checkBoxImage button in the cell it doesn't fire this event...       
}

Upvotes: 0

Views: 6070

Answers (2)

Nik
Nik

Reputation: 176

I use sample code below to implement check box button in cell (Xcode 7/ Swift 2.0):
-In viewDidLoad {}:(save check box state in each cell to .plist file)

 let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString


    let fnstring = (documentsPath as String)+"/yr-filename.plist"
    let fM = NSFileManager.defaultManager()
    //if (let  a != (fM.fileExistsAtPath(fnstring))) {
    if !(fM.fileExistsAtPath(fnstring)) {
        let onlyarr = NSMutableArray()
        for var i = 0 ; i < 5; ++i{ // number of sections

            var arr = NSArray()
            switch i { // number cell in each section
                case 0: arr = [Int](count: 12, repeatedValue: 0) // 0 means unchecked box.
                case 1: arr =  [Int](count: 13, repeatedValue: 0)
                case 2: arr =  [Int](count: 14, repeatedValue: 0)
                case 3: arr =  [Int](count: 15, repeatedValue: 0)
                case 4: arr =  [Int](count: 16, repeatedValue: 0) 
                default: arr = [Int]()   
            }
            onlyarr.addObject(arr)
            }
            onlyarr.writeToFile(fnstring, atomically: false)  
    }  

- In override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { }

let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
    let fnstring = (documentsPath as String)+"/yr-filename.plist"
    let fM = NSFileManager.defaultManager()
    if fM.fileExistsAtPath(fnstring) {
    let chcklstDick = NSMutableArray(contentsOfURL: NSURL(fileURLWithPath: fnstring))
    let chcklstsortedCat: NSArray? = chcklstDick
    let ttt: NSMutableArray = chcklstsortedCat?.objectAtIndex(indexPath.section) as! NSMutableArray
        if ttt.count > 0 {  
            var img = UIImage()
             let j : Int = ttt.objectAtIndex(indexPath.row) as! Int
            NSLog("j: %i", j)
            if j > 0 {
                img = UIImage(named: "checked")!
            }else {
                img = UIImage(named: "unchecked")!
            }
            let bttn : UIButton = UIButton(type: UIButtonType.Custom)
            bttn.frame = CGRectMake(0, 0, img.size.width, img.size.height)
            bttn.setBackgroundImage(img, forState: UIControlState.Normal)
            bttn.addTarget(self, action:"chckBttnTapped:eventy:", forControlEvents: UIControlEvents.TouchUpInside)

            cell.accessoryView = bttn
        }

    }else {NSLog("nonononononononno")}  

- In func chckBttnTapped(sender: AnyObject, eventy event: AnyObject) { }

 let touches: NSSet = event.allTouches()!
    let touch: UITouch = touches.anyObject()! as! UITouch
    let crrntTouchPos : CGPoint = touch.locationInView(self.tableView)
    let idxpth: NSIndexPath = self.tableView.indexPathForRowAtPoint(crrntTouchPos)!
   if idxpth.row != NSNotFound {
       self.tableView(self.tableView, accessoryButtonTappedForRowWithIndexPath: idxpth)
    }  

-In override func tableView(tableView: UITableView, accessoryButtonTappedForRowWithIndexPath indexPath: NSIndexPath) { }

let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
    let fnstring = (documentsPath as String)+"/yr-filename.plist"
    let fM = NSFileManager.defaultManager()
    if fM.fileExistsAtPath(fnstring) {
        let chcklstDick = NSMutableArray(contentsOfURL: NSURL(fileURLWithPath: fnstring))
        let chcklstsortedCat: NSMutableArray? = chcklstDick 
        let ttt: NSMutableArray = chcklstsortedCat?.objectAtIndex(indexPath.section) as! NSMutableArray
        if ttt.count > 0 {
            let j : Int = ttt.objectAtIndex(indexPath.row) as! Int
            var newimg = UIImage()
            if j == 0 {
                newimg = UIImage(named: "checked")!
            }else {
                newimg = UIImage(named: "unchecked")!
            }

             let cell = tableView.dequeueReusableCellWithIdentifier("cellID", forIndexPath: indexPath)
            let bttn : UIButton = UIButton(type: UIButtonType.Custom)
            bttn.frame = CGRectMake(0, 0, newimg.size.width, newimg.size.height)
            bttn.setBackgroundImage(newimg, forState: UIControlState.Normal)

            bttn.addTarget(self, action:"chckBttnTapped:eventy:", forControlEvents: UIControlEvents.TouchUpInside)

            cell.accessoryView = bttn
            self.tableView.reloadData()
            self.tableView.reloadInputViews()
            ttt.replaceObjectAtIndex(indexPath.row, withObject: 1 - j)
            chcklstsortedCat?.replaceObjectAtIndex(indexPath.section, withObject: ttt)
            chcklstsortedCat?.writeToFile(fnstring, atomically: false)
        }
    }  

Hope its useful.

Upvotes: 2

Josh Gafni
Josh Gafni

Reputation: 2881

I know what you are trying to accomplish, but I would tackle it a different way. Perhaps in your model, you could have an array of tasks that are pending, and another array of tasks that are completed.

The number of sections can be 2. The number of rows in sections 0 and 1 can be the number of elements in the first and second arrays respectively.

When didSelectRowAtIndexPath is called, you can remove the item at that index in the first array and add the task to the second array. Then you must call tableView.reloadData().

I know you want to just pick up the row and change the placement of it, but in iOS the cells get reused. It's best to update the data source and then reload the table.

For the checkmarks, you can ensure that the items in Section 0 do not have the checkmark accessory, while the items in Section 1 do. You would set the accessory in cellForRowAtIndexPath after the cell has been dequeued.

Upvotes: 0

Related Questions