问题
I was trying to create a custom alert and I am getting mad trying to implement a completition handler on the buttons. I have tried a few things, the last, create func array to pass in the selector addTarget function of the UIButton, but not working. (where the ****** are)
The issue: "Argument of #selector does no refer to @obc method, property or initializer"
The difficult coding part I can't do is to configure the selector with some code I receive from my view controller where I create an object with the class below.
class Alert: NSObject {
func showAlert(){
if let window = UIApplication.shared.keyWindow {
//configure some constraints and animations
}
var buttons: [UIButton] = []
var buttonsFunc: [() -> Void ] = []
func addNewButton(title: String, handler: @escaping () -> Void) {
buttons.append(createButton(title: title))
buttonsFunc.append {
self.dismissAlert()
handler()
}
}
func setupButtons() {
for (index, button) in buttons.enumerated() {
boxView.addSubview(button)
//Here is the problem ***************************
button.addTarget(self, action: #selector(buttonsFunc[index]), for: .touchUpInside)
//More constraints(not important)
button.centerXAnchor.constraint(equalTo: boxView.centerXAnchor).isActive = true
button.widthAnchor.constraint(equalTo: (button.titleLabel?.widthAnchor)!).isActive = true
button.heightAnchor.constraint(equalToConstant: 25).isActive = true
}
}
func dismissAlert(){
//Animation to dismiss my alert
}
Other functions:
//Even if its not important the function i use to create the button
func createButton(title: String) -> UIButton {
let button = UIButton(type: .system)
button.backgroundColor = .clear
button.setTitle(title, for: .normal)
button.titleLabel?.sizeToFit()
button.setTitleColor(uPBlue, for: .normal)
button.titleLabel?.font = UIFont(name: uPFont, size: 20)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}
Any ideas how to fix this? Or maybe a totally different way. If it works i take it.
回答1:
So a selector is just the name of a function. A closure by definition is an anonymous function so you can't quite do it this way.
Lets try another route, define a new function to give to the buttons:
private func buttonPressed(sender: UIButton) {
}
Then lets give the buttons this function instead of the closure:
...
button.addTarget(self, action: #selector(Alert.buttonPressed(sender:)), for: .touchUpInside)
...
Now we can take advantage of tuples here. Instead of having two separate arrays we'll to one array with an adhoc data structure for our buttons:actions:
// var buttons: [UIButton] = []
// var buttonsFunc: [() -> Void ] = []
// Becomes
var buttonActionArray: [(button: UIButton, action: () -> Void)] = []
Now lets implement buttonPressed(sender:)
private func buttonPressed(sender: UIButton) {
for buttonTuple in buttonActionArray {
if buttonTuple.button === sender {
buttonTuple.action()
}
}
}
来源:https://stackoverflow.com/questions/43923281/custom-class-to-create-an-alert-with-buttons-how-to-add-a-completition-handler