Currently this code that executes a Tag Styled List, The issue remains when I want to try to pass the addTarget Action optionClicked to my UIViewController
DrawerView.swift
let menuOptions = ["Info", "Actions", "Users", "Patiens"]
menuOptions.forEach({
let button = UIButton()
button.setTitle($0, for: .normal)
if $0.contains(menuOptions[0]) {
button.style(with: .filled)
} else {
button.style(with: .outlined)
button.addTarget(self, action: #selector(optionClicked(_:)), for: .touchUpInside)
}
actionStackView.addArrangedSubview(button)
})
DrawerController.swift
class DrawerController: UIViewController {
var shareView = DrawerView()
var viewModel: CarDetailViewModel?
override func loadView() {
shareView.viewModel = viewModel
view = shareView
}
@objc func optionClicked(_ sender: UIButton) {
let feedbackGenerator = UISelectionFeedbackGenerator()
feedbackGenerator.selectionChanged()
let optionClicked: String = sender.titleLabel?.text ?? "0"
switch optionClicked {
case "Actions": present(DrawerActionController(), animated: true, completion: nil)
case "Notifications":
let viewController = DrawerNotificationController()
viewController.carDetailViewModel = viewModel
present(viewController, animated: true, completion: nil)
case "Patients":
let viewUserController = DrawerUserController()
viewUserController.carPath = "9000"
present(viewUserController, animated: true, completion: nil)
default: break
}
}
}
Tried button.addTarget(self, action: #selector(optionClicked(_:)), for: .touchUpInside) but did not work out.
In the method button.addTarget(self, action: #selector(optionClicked(_:)), for: .touchUpInside)
you need to provide pointer to the viewController which will receive the action.
The easiest way in your case would be to create lazy variable DrawerView with DrawerController on the init and use the drawer controller in the button action.
DrawerView.swift
class DrawerView: UIView {
private unowned let drawerController: DrawerController
init(drawerController: DrawerController) {
self.drawerController = drawerController
}
... wherever is your code placed ...
let menuOptions = ["Info", "Actions", "Users", "Patiens"]
menuOptions.forEach({
let button = UIButton()
button.setTitle($0, for: .normal)
if $0.contains(menuOptions[0]) {
button.style(with: .filled)
} else {
button.style(with: .outlined)
button.addTarget(drawerController, action: #selector(DrawerController.optionClicked(_:)), for: .touchUpInside)
actionStackView.addArrangedSubview(button)
}
})
....
}
It's important you use unowned
or weak
to prevent retain cycles and memory leaks
To create the DrawerView you can use a lazy variable:
lazy var shareView: DrawerView = DrawerView(drawerController: self)
lazy will allow you to use self, you can also use optional and create the variable later, but that's basically what lazy does.
Hope it helps!