0

I'm working on my own alert implementation and for that I created AlertViewController.

My AlertViewController contains actions (buttons) and textFields. To add actions I use the following method:

func addAction(title: String, handler: (() -> Void)? = nil) -> Self {
    let button = UIButton()

    button.setTitle(title, for: .normal)
    button.setTitleColor(.label, for: .normal)
    if let handler = handler {
        button.addAction(handler)
    }

    actionsStackView.addArrangedSubview(button)
    return self
}

I use the following extension to be able to add a closure as an action on a UIButton (find here):

@objc class ClosureSleeve: NSObject {
    let closure: () -> Void

    init (_ closure: @escaping () -> Void) {
        self.closure = closure
    }

    @objc func invoke () {
        closure()
    }
}

extension UIButton {
    func addAction(for controlEvents: UIControl.Event = .touchUpInside, _ closure: @escaping () -> Void) {
        let sleeve = ClosureSleeve(closure)

        addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
        objc_setAssociatedObject(self, "[\(arc4random())]", sleeve, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
    }
}

I would like to be able to retrieve the textFields from my AlertViewController from a call to addAction in the following way:

AlertViewController(title: "Information")
    .addAction(title: "Send") { textFields in
        let text = textFields?.first?.text
    }
    .show(on: self)

When I do this I got the following error: Contextual closure type '() -> Void' expects 0 arguments, but 1 was used in closure body

I don't know how to do it at all, I looked on the internet without success because I don't know what to look for.

Edit: I have create a gist with the code of my AlertViewController here

R3J3CT3D
  • 226
  • 2
  • 10
  • The title of your question is not accurate. The trailing aspect is not relevant. –  Aug 30 '20 at 01:11
  • I don't see any text fields in your `AlertViewController`. Are the text fields properties of `AlertViewController`? Can you show how they are created and used? – Sweeper Aug 30 '20 at 01:27
  • @Jessy I know, that's why I specified in my question that I didn't know what to look for on the internet – R3J3CT3D Aug 30 '20 at 09:28
  • @Sweeper I added the code of my `AlertViewController` in a gist at the end of the question – R3J3CT3D Aug 30 '20 at 09:29
  • @R3J3CT3D I know you said that, but it seems that you know what a parameter and trailing closure are, from your code. So it's confusing; it seems like you have an idea of what you're looking for, but then just picked some terminology that's *kind of associated* with the problem, but not really. Confusing! –  Aug 30 '20 at 18:30
  • @Jessy I have the possibility to edit the title, what title would you suggest? – R3J3CT3D Aug 30 '20 at 20:37
  • I honestly can't tell what you're asking. See if you can whittle it down yourself, and find out! –  Aug 31 '20 at 00:38

1 Answers1

0

Capture only what you need. A capture list is different than the signature of your closure, which doesn't use any parameters.

If it's textFields:

alertViewController.addAction(title: "Add") { [textFields = alertViewController.textFields] in
    print(textFields)
}

Otherwise:

alertViewController.addAction(title: "Add") { [unowned alertViewController] in
    print(alertViewController.textFields)
}
  • When I try this I get the following error: `Variable used within its own initial value` – R3J3CT3D Aug 30 '20 at 09:30
  • Why is that? I tried it out and do not. So I think you should simplify your code, demonstrate where the error shows up, and then report back! –  Aug 30 '20 at 18:28
  • It's because I want to use `addAction` on `AlertViewController` initialisation and not on a instance like `alertViewController`. I have updated the question with the `AlertViewController` code and the code I would like to use. – R3J3CT3D Aug 30 '20 at 20:43
  • There's no way to do it with chaining because you don't have access to the `AlertViewController`. –  Aug 31 '20 at 00:37