2

When I tap a button in a custom cell and then scroll down (or up) another cell button is also tapped. I see that it's tapped because the button outlet that I created for the button is disabled.

My cellForRowAtIndexPath has a reuseIdentifier for the cell:

var cell: FeedTableViewCell? = tableView.dequeueReusableCellWithIdentifier("MusicCell") as? FeedTableViewCell

Considering I have the degueueReusableCellWithId in the cellForRowAtIndexPath do I need a prepareForReuse? When I add the prepareForReuse in my custom cell file, the cell just goes back to the default values (obviously because I reset it to the default values). Problem is I want it to keep the value of each indexPath.row.

This is how I'm querying the values:

 override func queryForTable() -> PFQuery {
        var query:PFQuery = PFQuery(className:"Music")

        if(objects?.count == 0)
        {
            query.cachePolicy = PFCachePolicy.CacheThenNetwork
        }

        query.orderByAscending("videoId")

        return query
    }

This is the numberOfRowsInSection and cellForRowAtIndexPath

 override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
     return  objects!.count
    }


   override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {

        var cell: FeedTableViewCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? FeedTableViewCell
        if(cell == nil) {
            cell = NSBundle.mainBundle().loadNibNamed("FeedTableViewCell", owner: self, options: nil)[0] as? FeedTableViewCell
        }
        if let pfObject = object {
               //I took out the irrelevant methods. I can add them if that makes a difference... 
                var votes:Int? = pfObject["votes"] as? Int
                if votes == nil {
                    votes = 0
        }
        cell?.votesLabel?.text = "\(votes!)"

}

I'm registering this in the viewDidLoad above the super.viewDidLoad()

 tableView.registerNib(UINib(nibName: "FeedTableViewCell", bundle: nil), forCellReuseIdentifier: cellIdentifier)

This is my button query in the customCell:

@IBAction func heartButton(sender: AnyObject) {
        if(parseObject != nil) {
            if var votes:Int? = parseObject!.objectForKey("votes") as? Int {
                votes!++

                parseObject!.setObject(votes!, forKey: "votes")
                parseObject!.saveInBackground()

                votesLabel?.text = "\(votes!)"
            }
        }
        heartOutlet.enabled = false
}

Any help and suggestions mean a lot.

Thank you.


REFRENCE LINKS I USED:

I referred to several links but they were in objective-c and didn't help:

UICollectionView Tap Selects More Than One Cell

How to use prepareForReuse method

I also referred to the docs, and that didn't help much.

Community
  • 1
  • 1
Lukesivi
  • 2,206
  • 4
  • 25
  • 43
  • Add the code of UITableView DataSource Methods – Harikrishnan Nov 26 '15 at 12:42
  • Where i'm querying and sending the data from the tableView? Or from the custom cell? @HarikrishnanT – Lukesivi Nov 26 '15 at 12:44
  • Tbale view data source methods include `cellForRowAtIndexPath`, `numberOfCellsInTableView` etc. please post the code of `cellForRowAtIndexPath`(and `willDisplayCell` if you are using that too). There has to be something wrong you are doing in there that causes the issue. – Harikrishnan Nov 26 '15 at 12:47
  • Just updated the question, thank you @HarikrishnanT – Lukesivi Nov 26 '15 at 12:52

1 Answers1

2

From the code you have posted, it is clear that you are not setting the enabled property of the UIButton with respect to the DataSource(The array and its objects you are using to load the tableview, that is the elements in objects array). Whatever objects that array contains, add a property to determine if the condition for the button should be true or false, and then in cellForRowAtIndexPath set the enabled property of the button according to that. When the button is clicked, add a callback to the ViewController(using a delegate) and set the property there.

Sample Code

In custom cell class:

protocol CellButtonDelegate
{
    func buttonClicked(cell : PFTableViewCell)
}

public var delegate : CellButtonDelegate?

public var buttonEnabled : Bool?
{
    get
    {
        return heartOutlet.enabled
    }
    set
    {
        heartOutlet.enabled = newValue
    }
}

@IBAction func heartButton(sender: AnyObject) {
        if(parseObject != nil) {
            if var votes:Int? = parseObject!.objectForKey("votes") as? Int {
                votes!++

                parseObject!.setObject(votes!, forKey: "votes")
                parseObject!.saveInBackground()

                votesLabel?.text = "\(votes!)"
            }
        }
        delegate?.buttonClicked(self)
}

In ViewController:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell? {

        var cell: FeedTableViewCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? FeedTableViewCell
        if(cell == nil) {
            cell = NSBundle.mainBundle().loadNibNamed("FeedTableViewCell", owner: self, options: nil)[0] as? FeedTableViewCell
        }
        if let pfObject = object {
               //I took out the irrelevant methods. I can add them if that makes a difference... 
                var votes:Int? = pfObject["votes"] as? Int
                if votes == nil {
                    votes = 0
        }
        cell?.buttonEnabled = objects[indexPath.row].isEnabled //The new property you need to add. true by default
        cell?.delegate = self //Make sure you implement the delgate
        cell?.votesLabel?.text = "\(votes!)"    
        return cell?
}

func buttonClicked(cell : PFTableViewCell)
{
     //Here, get the indexPath using the cell and assign the new property in the array.
}

Please note that the above code is rough. Just get the idea from the code and implement it as per your requirement.

Harikrishnan
  • 7,765
  • 13
  • 62
  • 113
  • I'm using ParseUI to get the objects, so `objects` array is a ParseUI property that stores those objects. Can you provide some sample code? I'm having trouble understanding the logic of where this should be placed. Isn't it only relevant in the `cellForRowAtIndexPath`? Why would it be relevant in the `objects` array if I'm having a problem with the UIButton and the datasource? @HarikrishnanT – Lukesivi Nov 26 '15 at 13:06
  • Sample code added. You will have to make some changes in the current logic after referring the code I posted. – Harikrishnan Nov 26 '15 at 13:16
  • Trying it now! Thanks a lot! – Lukesivi Nov 26 '15 at 13:19
  • 2 problems: I get this error: `Cannot assign value of type "FeedTableViewController" to type CellButtonDelegate?` for this link: ' cell?.delegate = self` I added the delegate in the cell like this: `var delegate : CellButtonDelegate?` right under the class definition of the cell. and for this function: `func buttonClicked(cell : PFTableViewCell){ cell.buttonEnabled = objects![indexPath.row].isEnabled = true }` which I put in the `cellForRowAtIndexPath` right under the other methods and i get this error: `value of type PFTableViewCell has no member buttonEnabled`. Suggestions? – Lukesivi Nov 26 '15 at 13:29
  • I'm also getting an error when adding the delegate to the class definition*. @HarikrishnanT – Lukesivi Nov 26 '15 at 13:51
  • Delegate shouldn't be added in class definition, put it right outside the class definition below the import statements. I thought you were aware of the basic syntax. :-) – Harikrishnan Nov 26 '15 at 14:26
  • Hey, I did add it there but I got an error so I declared in right below... EDIT: Now i fixed it and added it on the top. I got it initialized and it works now. My issue is making a an array and adding boolean condition for each button. I can't make it a dictionary, which is what I'm trying. @HarikrishnanT – Lukesivi Nov 26 '15 at 14:30
  • The proper way of doing it adding a boolean property to the object of the array `objects` to determine if the button has to be enabled or not. :-) – Harikrishnan Nov 26 '15 at 14:36
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/96263/discussion-between-lukesivi-and-harikrishnan-t). – Lukesivi Nov 26 '15 at 14:36
  • How do I add a property to the array objects to determine if the button has been enabled or not? Sorry for the newbie questions! :) @Harikrishnan – Lukesivi Nov 26 '15 at 14:47