为什么 UIAlertAction 的处理程序需要有一个引用 UIAlertAction 的参数?

Why is a UIAlertAction's handler required to have a parameter that references the UIAlertAction?

我正在使用一个简单的按钮,当按下该按钮时,它会运行我创建的功能。

原来我是这样写代码的:

func askQuestion() {
     // runs code to ask a question
}

@IBAction func buttonTapped(_ sender: UIButton) {
     let ac = UIAlertController(title: title, message: "You tapped the button.", preferredStyle: .alert)
     ac.addAction(UIAlertAction(title: "Continue", style: .default, handler: askQuestion))
    present(ac, animated: true)

但是returns一个错误:

Cannot convert value of type '() -> ()' to expected argument type '((UIAlertAction) -> Void)?'

将以下参数添加到 askQuestion() 时修复:

askQuestion(action: UIAlertAction! = nil)

为什么传递给 UIAlertAction 的处理程序方法要求它接受 UIAlertAction 参数?这似乎是一个不必要的步骤,但我认为这可能是一种扫描代码以寻找此功能由按钮触发的提示的方法。

你需要

func askQuestion(_ action:UIAlertAction){} // ->() is the void return here 

necessary/not UIAlertAction 处理程序有 UIAlertAction -> () 回调,所以你必须执行,有时你会执行

alert.addAction(UIAlertAction.......{ (action) in }

因此了解有关当前操作的一些详细信息(例如标题或样式)很有用

您可以让一个处理程序负责处理多个操作

var continueAction: UIAlertAction!
var cancelAction: UIAlertAction!

override func viewDidLoad() {
    super.viewDidLoad()

    continueAction = UIAlertAction(title: "Continue", style: .default, handler: masterHandler)
    cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: masterHandler)
}

//...

 let ac = UIAlertController(title: title, message: "You tapped the button.", preferredStyle: .alert)
 ac.addAction(continueAction)
 ac.addAction(cancelAction)

就我个人而言,我不知道您为什么要这样做,但是 API 设计人员认为让您可以灵活地设计最能满足您需求的解决方案是个好主意。

因此,在大多数情况下,虽然我很欣赏它看起来很奇怪(尤其是当您可以使用闭包时),但我确实很高兴有可用的信息来做出我自己的选择

如果警报中有一个文本字段并且您需要获取该文本怎么办?

如果同一功能由多个警报共享并且您需要知道这是哪个警报(完全有可能)怎么办?

如果这是一个带有 属性 或您需要访问的方法的 UIAlertController 子类怎么办? (是的,我已经做到了。)

您需要对警报的引用!你需要它作为一个已经很弱的引用,所以如果你使用尾随闭包,你就不会得到一个保留周期。因此,动作处理程序被赋予一个作为参数。

相信我,如果您没有得到对警报的引用,您迟早会发现自己处于愤怒和受阻的境地。