0

I have a few UITableView instances throughout my application that all contain instances of a UITableViewCell subclass, called BeerTableViewCell. In my subclass, I added a couple instances of UILabel and a few instances of UIButton. The code for BeerTableViewCell follows:

import UIKit
import CoreData




class BeerTableViewCell: UITableViewCell {




//////////////////////////////////////////////////////////////
//      MARK: - Properties
//////////////////////////////////////////////////////////////

    var beerNameLabel = UILabel()
    var breweryNameLabel = UILabel()
    var beerCategoryReferenceImageView = UIImageView()
    var likeButton = UIButton()
    var tryButton = UIButton()
    var dislikeButton = UIButton()
    var deleteButton = UIButton()
    var categoryButtonsArray = [UIButton]()


//////////////////////////////////////////////////////////////
//      MARK: - View Lifecycle
//////////////////////////////////////////////////////////////

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
        self.autoresizingMask = .FlexibleHeight
        self.clipsToBounds = true
    }




    override func layoutSubviews() {
        super.layoutSubviews()
        beerNameLabel.frame = CGRectMake(10, 8, self.bounds.size.width - 40, 26)
        beerNameLabel.font = UIFont(name: "Avenir Next", size: 18)
        contentView.addSubview(beerNameLabel)

        breweryNameLabel.frame = CGRectMake(10, 32, self.bounds.size.width - 40, 20)
        breweryNameLabel.font = UIFont(name: "Avenir Next", size: 14)
        breweryNameLabel.alpha = 0.5
        contentView.addSubview(breweryNameLabel)

        beerCategoryReferenceImageView.frame = CGRectMake(self.bounds.size.width-35, 20, 20, 20)
        beerCategoryReferenceImageView.image = UIImage()
        contentView.addSubview(beerCategoryReferenceImageView)

        likeButton.frame = CGRectMake(20, 70, 30, 30)
        contentView.addSubview(likeButton)

        tryButton.frame = CGRectMake(90, 70, 30, 30)
        contentView.addSubview(tryButton)

        dislikeButton.frame = CGRectMake(160, 70, 30, 30)
        contentView.addSubview(dislikeButton)

        deleteButton.frame = CGRectMake(230, 70, 30, 30)
        contentView.addSubview(deleteButton)

        let likeNormalImage = UIImage(named: "like-button")
        let likeSelectedImage = UIImage(named: "like-button")
        likeButton.setImage(likeNormalImage, forState: .Normal)
        likeButton.setImage(likeSelectedImage, forState: .Selected)

        let tryNormalImage = UIImage(named: "try-button")
        let trySelectedImage = UIImage(named: "try-button")
        tryButton.setImage(tryNormalImage, forState: .Normal)
        tryButton.setImage(trySelectedImage, forState: .Selected)

        let dislikeNormalImage = UIImage(named: "dislike-button")
        let dislikeSelectedImage = UIImage(named: "dislike-button")
        dislikeButton.setImage(dislikeNormalImage, forState: .Normal)
        dislikeButton.setImage(dislikeSelectedImage, forState: .Selected)

        let deleteNormalImage = UIImage(named: "delete-button")
        let deleteSelectedImage = UIImage(named: "delete-button")
        deleteButton.setImage(deleteNormalImage, forState: .Normal)
        deleteButton.setImage(deleteSelectedImage, forState: .Selected)1

        likeButton.addTarget(self, action: "handleButtonPress", forControlEvents: .TouchUpInside)
        tryButton.addTarget(self, action: "handleButtonPress", forControlEvents: .TouchUpInside)
        dislikeButton.addTarget(self, action: "handleButtonPress", forControlEvents: .TouchUpInside)
        deleteButton.addTarget(self, action: "handleButtonPress", forControlEvents: .TouchUpInside)

        categoryButtonsArray.append(likeButton)
        categoryButtonsArray.append(tryButton)
        categoryButtonsArray.append(dislikeButton)
} 




//////////////////////////////////////////////////////////////
//      MARK: - States
//////////////////////////////////////////////////////////////

    override func setSelected(selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        // Configure the view for the selected state
}



//////////////////////////////////////////////////////////////
//      MARK: - Helpers
//////////////////////////////////////////////////////////////

    func handleButtonPress() {
        println("Button Pressed")
    }


}

I am having difficulty finding a way to perform an action when the buttons are pressed in any of my UITableView instances. I was able to successfully add an action to the buttons that will print out that the a button was pressed (println("Button Tapped"):

I am having trouble figuring out how to implement a delegate method to handle the button presses. Every tutorial that I have found has implemented the UIButton actions via Interface Builder. Do I need to use Interface Builder to create the buttons and hook actions to them? As you can see, I am currently creating my buttons in code, but the tutorials that I have found are mostly doing it this way.

A little guidance would be greatly appreciated!

Resolved:

In order for the view controller that conforms to the delegate protocol to allow the assignment of self to the cell's delegate, I simply had to implement the delegate method in the view controller. If I did not add the delegate method, Xcode would not allow the assignment.

Community
  • 1
  • 1
Nick Kohrn
  • 5,779
  • 3
  • 29
  • 49

1 Answers1

2

You have a couple of options. You can call addTarget:action:forControlEvents: in cellForRowAtIndexPath: instead of in your cell class (passing self as the target), or you can use a delegate protocol (in which case, you would set yourself as delegate of the cell in cellForRowAtIndexPath). Create the delegate protocol in the cell class, add a delegate property, and call the delegate method from the button's action method. You would implement the delegate method in your table view controllers to respond appropriately to the button touch.

rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • The delegate option is what I was leaning toward. That definitely made it easier for me. Now, in the protocol, do I just need to capture the indexPath of the cell that receives the button press so that I can act on the object that the cell represents? – Nick Kohrn May 01 '15 at 22:29
  • @bnkohrn Yes, you need to do that. Usually I use the method , indexPathForRowAtPoint:, to get the indexPath of the button's cell. – rdelmar May 01 '15 at 22:31
  • I created a protocol as well as the delegate property in the `UITableViewCell` subclass. Then, I added the delegate to the class declaration at the top of my view controller that I want to conform to the protocol. However, when I try to set the delegate of the `UITableViewCell` subclass in `cellForRowAtIndexPath:` of the view controller to 'self', I get an error that says "Cannot assign a value of type 'CategoryTableViewController' to a value of type 'BeerTableViewCellDelegate?'". I must be missing something, but I am not able to figure out what. – Nick Kohrn May 01 '15 at 23:38
  • @bnkohrn So you added 'BeerTableViewCellDelegate` to your class declaration for the table view controller? Show the code you're adding in cellForRow to set the delegate. – rdelmar May 01 '15 at 23:42
  • `override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("beerCell", forIndexPath: indexPath) as! BeerTableViewCell configureCell(cell, indexPath: indexPath) cell.delegate = self return cell }` – Nick Kohrn May 01 '15 at 23:43
  • @bnkohrn That looks like it should work, so I don't know why it won't let you set the delegate. – rdelmar May 01 '15 at 23:45