How can I call other class button - Swift

I have this newCell class:

class newCell: UITableViewCell {

override func awakeFromNib() {
    super.awakeFromNib()
    // Initialization code
}

override func setSelected(selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    // Configure the view for the selected state
}
@IBOutlet weak var recipeImage: UIImageView!

@IBOutlet weak var recipeTitle: UILabel!

@IBOutlet weak var favoriteButton: UIButton!

@IBAction func favoriteAction(sender: AnyObject) {


}

In the HomeViewController, I use this newCell class as a prototype cell for my table view. It is working fine for texts and images. My doubt is, how can I handle a button of this prototype cell in my HomeViewController? For example, I would like the button to change its image according to the array passed.

  override func viewDidLoad() {
    super.viewDidLoad()

   var recipesFeed = PFQuery(className: "Recipe")

    recipesFeed.findObjectsInBackgroundWithBlock { (objects, error) -> Void in

        if let recipes = objects {

        self.recipes.removeAll(keepCapacity: true)
        self.recipeImages.removeAll(keepCapacity: true)
        self.isFavorite.removeAll(keepCapacity: true)


            for recipe in recipes{

                self.recipes.append(recipe["title"] as! String)
                self.recipeImages.append(recipe["image"] as! String)
                self.isFavorite.append(recipe["isFavorite"] as! Int)

                self.tableView.reloadData()

            }

        }

    }

}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let myCell = self.tableView.dequeueReusableCellWithIdentifier("prototypeCell") as! newCell

 images[indexPath.row].getDataInBackgroundWithBlock { (image, error) -> Void in

        if let downloadedImage = UIImage(data: image!){

            myCell.recipeImage.image = downloadedImage

        } else {

            myCell.recipeImage.image = UIImage(named: "background_recipe_image.png")
        }


    }

    myCell.recipeTitle.text = recipes[indexPath.row]
    //begin what I try and doesn't work
    myCell.favoriteAction(sender: AnyObject) {

    if isFavorite[indexPath.row] == 1 { 
      if let image = UIImage(named: "star vector.png") {

        myCell.favoriteButton.setImage(image, forState: .Normal)


    }

    } else {

    if let image = UIImage(named: "star vector blank.png") {

        myCell.favoriteButton.setImage(image, forState: .Normal)

    }
    }
    }
    //end what I try and doesn't work
    return myCell
}

Upvotes: 0

Views: 118

Answers (2)

Ike10
Ike10

Reputation: 1595

So my method for accessing the isFavorited array in the HomeViewController is to use a delegation pattern with two protocols.

protocol hasFavBtn {

  var delegate: FavBtnDelegate! { get set }
  var delegateTableView: UITableView! { get set }

}

protocol FavBtnDelegate {

  var isFavorited: [Int] { get set }

}

In order for this to work the NewCell class should conform to the hasFavBtn protocol and the HomeViewController should conform to the FavBtnDelegate protocol. Like So:

HomeViewController

class ViewController: UITableViewController, FavBtnDelegate  {

  var isFavorited = [0, 0, 0, 0, 1]

  let newCellStr = "NewCell"

  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let newCell = tableView.dequeueReusableCellWithIdentifier(newCellStr) as! NewCell

    newCell.delegate = self
    newCell.delegateTableView = tableView

    return newCell
  }
}

The important thing to notice here are:

  1. In cellForRowAtIndexPath the delegate and delegateTableView properties for the instance of the NewCell class are defined before the newCell constant is returned.

  2. The isFavorited variable is set as described in the FavBtnDelegate protocol.

NewCell.swift

class NewCell: UITableViewCell, hasFavBtn {

  var delegate: FavBtnDelegate!
  var delegateTableView: UITableView!

  @IBOutlet weak var favoriteBtn: UIButton!

  let blankStarImg = UIImage(imageLiteral: "blankStar")
  let fullStarImg = UIImage(imageLiteral: "fullStar")

  override func awakeFromNib() {
    super.awakeFromNib()
    let blankStarImg = UIImage(imageLiteral: "blankStar")
    favoriteBtn.setBackgroundImage(blankStarImg, forState: .Normal)
  }

  @IBAction func favoriteBtnPressed(sender: AnyObject) {
    let locationInCell = CGPoint(x: (sender.frame.maxX - sender.frame.minX)/2, y: (sender.frame.maxY - sender.frame.minY)/2)
    let locationInDelegateTableView = convertPoint(locationInCell, toView: delegateTableView)

    if let indexPath = delegateTableView.indexPathForRowAtPoint(locationInDelegateTableView) {
      if delegate.isFavorited[indexPath.row] == 1 {
        favoriteBtn.setBackgroundImage(fullStarImg, forState: .Normal)
      }
    }
  }

As others have said it is here, in that the UITableViewCell subclass, that you should define the @IBAction for the favorite Button. You can reference the tableView and the isFavorited array via the delegate property because in cellForRowAtIndexPath the value for the delegateTableView property was set to the tableView of the HomeViewController and the delegate property was set to the HomeViewController instance (using the self keyword).

So favoriteBtnPressed function finds the center (CGPoint) of the button that was pressed and then converts that to the coordinate system of the delegateTableView and thereby the tableView in the HomeViewController. Using the converted center of the button in the tableView's coordinate system the code uses an if let binding to safely unwrap the indexPath for the converted center. Then using the unwrapped indexPath and the delegate property you can check whether the HomeViewController's isFavorited array value at the given indexPath is equal to 1 and adjust the image accordingly.

The swift's protocols and delegation pattern are very powerful and useful for many things. You can read more about them here: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html

Also, note that I put my images in the Assets.xcassets file so I used the imageLiteral initializer to get them.

Hope this helps! If you have any questions, feel free to ask!

Upvotes: 1

Daniel T.
Daniel T.

Reputation: 33967

You have an action favoriteAction in your tableviewcell already. The simple solution to your problem is to pass the array of possible images into the tableviewcell when it is dequeued and then you put the code that swaps out the images in the favoriteAction IBAction.

If you can't figure out what to do from my description above, I can post some code, but try to figure it out first. I think it's a good learning exercise.

Upvotes: 1

Related Questions