custom apps
custom apps

Reputation: 533

Delegating action through protocol not working swift

I needed to delegate a click action for my UIView class to my UIViewController class since Swift does not support multiple class inheritance. So i wanted it such that once a button is clicked on my subview, a function in my BrowserViewController class is called.

I am using a protocol to achieve this, but on the function does not triggered when the button is tapped. Please help me out.

View Controller


class BrowseViewController: UIViewController {

  var categoryItem: CategoryItem! = CategoryItem() //Category Item

  private func setupExplore() {
    //assign delegate of category item to controller
    self.categoryItem.delegate = self
  }
}

// delegate function to be called
extension BrowseViewController: ExploreDelegate {
  func categoryClicked(category: ProductCategory) {
    print("clicked")
    let categoryView = ProductByCategoryView()
    categoryView.category = category
    categoryView.modalPresentationStyle = .overCurrentContext

    self.navigationController?.pushViewController(categoryView, animated: true)
  }
}

Explore.swift (subview)

import UIKit

protocol ExploreDelegate: UIViewController {
  func categoryClicked(category: ProductCategory)
}

class Explore: UIView {
  var delegate: ExploreDelegate?

  class CategoryItem: UIView {
    var delegate: ExploreDelegate?
    var category: ProductCategory? {
      didSet {
        self.configure()
      }
    }

    var tapped: ((_ category: ProductCategory?) -> Void)?

    func configure() {
      self.layer.cornerRadius = 6
      self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.categoryTapped)))
      self.layoutIfNeeded()
    }

    @objc func categoryTapped(_ sender: UIGestureRecognizer) {
      delegate?.categoryClicked(category: ProductCategory.everything)
      self.tapped?(self.category)
    }
  }
}

Upvotes: 0

Views: 678

Answers (3)

Fattie
Fattie

Reputation: 12648

Simply add a print statement inside categoryTapped.

You will then know if it is actually being tapped.

A million things could go wrong, for example, you may have forget to set the UIView to allow intertaction.

After checking that. Next add another print statement inside categoryTapped which shows you whether or not the delegate variable is null.

You'll quickly discover the problem using simple print statements.

print("I got to here!")

It's that easy.

And what about

if delegate == nil { print("it is nil!! oh no!" }
else { print("phew. it is NOT nil.") }

Debugging is really that easy at this level.

Next add a print statement inside setupExplore()

func setupExplore() {
  print("setup explore was called")
  ....

See what happens.

Upvotes: 1

Leejay Schmidt
Leejay Schmidt

Reputation: 1203

There are a few things that could cause the delegate method to not be triggered in this code:

  1. Ensure that isUserInteractionEnabled = true on your CategoryItem. This is probably best done in either the configure() function in the CategoryItem or in the setupExplore() function of the BrowseViewController.
  2. Make sure that the setupExplore() function on the BrowseViewController is being called, and that the category is being set on the CategoryItem to trigger the configure function. Otherwise, either the delegate or the gesture recognizer might not being set.

Side Note - weak vs strong delegate

On a side note, it is usually best practice to make your delegate properties weak var rather that having them be a strong reference, as this makes them prone to strong retain cycles.

Therefore, you might want to consider making the var delegate: ExploreDelegate? on your CategoryItem into weak var delegate: ExploreDelegate?. For more information on this problem, view this post.

Upvotes: 0

Mahsa Yousefi
Mahsa Yousefi

Reputation: 236

I don't see any piece of code which sets the delegate.

First of all, define delegate as a property inside CategoryItem class, Then you must set the current instance of BrowseViewController to the delegate variable of CategoryItem. Now you can expect your method being called.

Upvotes: 0

Related Questions