Custom class to create an Alert with Buttons. How to add a completition handler?

好久不见. 提交于 2019-12-12 03:38:16

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!