Reputation: 533
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
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
Reputation: 1203
There are a few things that could cause the delegate method to not be triggered in this code:
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
.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.weak
vs strong
delegateOn 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
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