The code below compiles fine, but crashes with an unrecognized selector sent to instance
error.
I have one class that inherits from UIViewController
:
class Controller: UIViewController {
override func viewDidLoad() {
let toolbarWrapper = CustomToolbarWrapper(view: view, target: self)
let toolbar = toolbarWrapper.toolbarView
view.addSubview(toolbar)
... Other code ...
}
}
And another class that is just a wrapper for a UIView
and contains buttons:
class CustomToolbarWrapper {
var toolbarView: UIView
init(view: UIView, target: Any) {
let height: CGFloat = 80
toolbarView = UIView(frame: CGRect(x: 0, y: view.frame.height - height, width: view.frame.width, height: height))
let button = UIButton()
... Some button layout code ...
button.addTarget(target, action: #selector(CustomToolbar.buttonTapped(_:)), for: .touchUpInside)
toolbarView.addSubview(button)
}
@objc static func buttonTapped(_ sender: Any) {
print("button tapped")
}
}
For the sake of clarity, I left out a large chunk of code and kept what I thought was necessary. I think that my code doesn't work because of my misunderstanding of the how the target works in the addTarget
function. Normally, I would just use self
as the target of my button's action, so I just tried to pass along self
from the view controller to the CustomToolbarWrapper
's init
function.
What else I have tried:
Changing the button's target from target
to self
like this:
button.addTarget(self, action: #selector(CustomToolbar.buttonTapped(_:)), for: .touchUpInside)
results in the app not crashing anymore. Instead, however, I believe that line of code fails to do anything (which doesn't throw an error for some reason?) because attempting to print button.allTargets
or even button.allTargets.count
results in the app crashing at compile time, with an EXC_BREAKPOINT error and no error description in the console or the XCode UI (which just confuses me even more because there are no breakpoints in my code!).
Also, making buttonPressed(_:)
non-static does not change any of the previously mentioned observations.
Also, to make sure the button could in fact be interacted with, I added this in the viewDidLoad()
of Controller
:
for subview in toolbar.subviews? {
if let button = subview as? UIButton {
button.addTarget(self, action: #selector(buttonPressed(_:)), for: .touchUpInside)
}
}
and added a simple testing method to Controller
for the button:
@objc func buttonPressed(_ sender: UIButton) {
print("Button Pressed")
}
And running the code did result in "Button Pressed" being printed in the console log, so the button should be able to be interacted with by the user.
Feel free to let me know if you think this is not enough code to figure out the problem, and I will post more details.
Edit
I prefer to keep the implementation of the button's action in the CustomToolbarWrapper
class to prevent repeating code in the future, since the action will be the same no matter where an instance of CustomToolbarWrapper
is created.