你应该如何处理 UIAlertAction 的闭包参数

How should you handle closure arguments for UIAlertAction

我一直在尝试创建一个 UIAlertAtion,它也有一个处理程序。我阅读了 this 问题的答案并知道如何去做。

我的问题只是关于它的关闭部分。

1) 我知道我可以写:{alert in println("Foo")} 或者 {_ in println("Foo")} 但我 不能{println("Foo")}。在评论here中解释是因为你需要处理参数action

这是否意味着由于处理程序是 (UIAlertAction) -> Void)? 类型,我必须始终捕获传递的 alertAction?


2) 我还阅读了 this,答案基本上是说你可以传入一个函数作为你的参数,但该函数应该采用 UIAlertAction -> Void 类型的东西,我写道:

private func anything(action : UIAlertAction) {
    print("hello")
}

然后这样写我的警报动作:

let anotherAction = UIAlertAction(title: "hi", style: UIAlertActionStyle.Default,
 handler: anything(action)) // error: Use of unresolved identifier 'action'

搞不懂为什么我会收到那个错误


3) 在评论中它还说:但除此之外你不必在swift中写UIAlertActionStyle.Default。 .默认也有效

我尝试不使用样式来编写,因此它会默认为 .Default

let sendLogAction = UIAlertAction(title: "Log") { action in print("goodbye")}

但随后出现以下错误:

'(title: String, (_) -> ())' (aka '(title: String, _ -> ())') is not convertible to '(title: String?, style: UIAlertActionStyle, handler: ((UIAlertAction) -> Void)?)' (aka '(title: Optional, style: UIAlertActionStyle, handler: Optional ()>)'), tuples have a different number of elements


4) 同时阅读 this 答案。我不明白为什么我们需要传入 alert 这没有意义。并不是说我们不知道警报的类型是什么……我们不是已经定义了它的类型吗?!!任何人都可以解释传递操作本身通常在哪里有用,我的意思是我们可以用它做什么?


我知道这是写成 4 个问题,但我认为这实际上只是一个基础问题。我在我正在操场上工作和玩耍的项目中广泛 read、使用了 closures/completion 处理程序,但我仍然感到困惑。

  1. 是的,您必须始终处理参数。它是签名的一部分,不容忽视。它也是特殊的 Swift 语法,能够删除 handler 参数,因为它是最后一个参数并且是一个闭包参数。

  2. anything(action) 更改为 anything 就像您 link 更改为的示例一样。

  3. 你误会了。他们并不是说您可以删除样式参数。他们说你可以从 UIAlertActionStyle.Default 中删除 UIAlertActionStyle 意味着你只需要将 .Default 作为参数传递给样式参数。

  4. 您想要一个示例,说明处理程序的 action 参数在哪里有用。真的没有太多用处。唯一的属性是标题、样式以及是否启用。后者毫无意义,因为如果调用了处理程序,您就知道它已启用。唯一可能的用途是标题或样式需要在处理程序中使用,并且它们在创建时没有硬编码到警报操作中。通过访问处理程序中的标题或样式属性,您可以轻松访问创建操作时使用的实际值。

1) UIAlerAction 初始化方法定义有 3 个参数,最后一个参数是 (UIAlertAction -> Void)?这意味着你可以有一个“无名”函数(又名闭包)或一个 nil(由可选符号 ? 指定)。如果您选择不指定最后一个参数,您可以像这样创建 UIAlertController

alert.addAction(UIAlertAction(title: "test", style: .default, handler: nil))

但是如果你想指定最后一个参数(不是 nil),那么你必须提供一个将 UIAlertAction 作为参数并且 return 没有任何参数(Void)的闭包。参考您的 link,他只是使用他为简单起见已经创建的“警报”常量。

要回答您的问题“这是否意味着……”,答案是肯定的,因为第三个参数的定义:(UIAlertAction) -> Void)?

2) 您收到错误是因为您传递了参数(操作)。试试让

anotherAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default,
 handler: anything)

你应该不会出错。

3) UIAlertAction 只有(我相信)一个初始化方法,因此您需要提供所有三个参数来创建它。请参阅我的 1) style:.default 答案。这是一种调用 Swift 枚举的新方法。顺便说一句,所有枚举都必须是小写的,所以 .default 不是 .Default`enter code here

alert.addAction(UIAlertAction(title: String?, style: UIAlertActionStyle, handler: ((UIAlertAction) -> Void))

4) 从答案中可以看出,您有 link。你可以使用常量 'alert' (UIAlertAction) 来做任何你想做的事情,比如检查样式和做一些事情。

func anything(alert: UIAlertAction!) {
    print("somehandler")
    switch alert.title {
    case "OK"?:
      print("title is OK")
    default:
      print("title is not OK")
    }
  }

rmaddy 的回答就足够了,但作为 OP :) 我找到了问题的根本原因:

我对参数处理程序缺乏理解,处理程序的类型为:(UIAlertAction) -> Void)? 即 closure/function

处理程序只需要一个函数名称,一旦您提供该函数,它将填写该函数的输入本身

传递anything作为处理程序,即函数名称。

UIAlertAction 的 internal 实现有 some line like handler(action) which would use anything which is of type(UIAlertAction) -> Void)?, 注入 action (传递给它)最终做 anything(action).

话虽如此,您的 anything(input: UIAlertAction) 应该做一些有意义的事情。 (已经在 rmaddy 的评论中讨论过)


另一个解决方案是 提供一个函数,而是在尾随闭包中使用 captured 操作并做任何你喜欢的事情用它做。

let retryAction = UIAlertAction(title: returnTitle(), style: UIAlertActionStyle.Default) { action in
switch action.title {
        case "OK":
        okFunc()
        case "cancel":
        cancelFunc()
        default:
        defaultFunc()
        }
      }

只有当您动态地获得代码时,这种切换才有价值,否则您知道它的价值的磁贴没有附加值切换。