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

Posted

技术标签:

【中文标题】你应该如何处理 UIAlertAction 的闭包参数【英文标题】:How should you handle closure arguments for UIAlertAction 【发布时间】:2016-11-30 16:48:44 【问题描述】:

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

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

1) 我知道我可以写:alert in println("Foo")_ in println("Foo"),但我不能println("Foo")。在 cmets here 中进行了解释,因为 您需要处理参数操作

这是否意味着由于处理程序的类型为(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) 在 cmets 中它还说:但除此之外,您不必快速编写 UIAlertActionStyle.Default。 .Default 也有效

我尝试不使用该样式进行写作,因此默认为.Default

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

然后我收到以下错误:

'(title: String, (_) -> ())' (aka '(title: String, _ -> ())') 不是 可转换为 '(title: String?, style: UIAlertActionStyle, handler: ((UIAlertAction) -> Void)?)' (aka '(title: Optional, style: UIAlertActionStyle,处理程序:可选 ()>)'),元组 有不同数量的元素


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


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

【问题讨论】:

#4 没有意义。你指的是什么alert @rmaddy switch action.style...他正在切换警报,但他还没有定义:style: .Default 他没有切换alert。他正在切换action.style。无论哪种方式,该 switch 语句只是一个示例。但这毫无意义。没有人会在真正的代码中这样做,因为你已经知道你设置了什么样式。 @rmaddy 是的,我用错了词,因为有时我看到人们写 action in 有时 alert in 没有区别......但毫无意义。所以对于我的 4 号,我要求提供一个很好的例子来说明捕获的 action 的使用位置。 【参考方案1】:

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

    anything(action) 更改为anything,就像您链接到的示例一样。

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

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

【讨论】:

1) 像尾随关闭一样下降? 2)哈!我在示例中没有看到上面的行。虽然这样做需要self.anything,但我需要避免内存循环 3)哈! 4)例如您的意思是标题是动态来自服务器的,可能是成功也可能是失败,然后关闭的行为会根据标题而改变? 4) 您可能有一系列动态按钮,因此标题不是硬编码的。然后处理程序可能需要将选择的标题传递给其他方法调用。这只是一个可能的例子。 关于需要用 self 引用任何东西。我确实理解为财产这样做的必要性,但我不明白为函数这样做的必要性。你能解释一下吗? 这是一个完全独立的讨论。我建议您发布一个特定于该问题的新问题(在确保它不重复之后)。【参考方案2】:

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

我对参数处理程序缺乏了解,处理程序类型为:(UIAlertAction) -> Void)? 即闭包/函数

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

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

UIAlertAction 的 internal 实现有 some 行,例如 handler(action),它将使用类型为(UIAlertAction) -> Void)?anything,注入 action(传递到它)最终做anything(action)

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


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

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

这种切换只有在您动态地获得代码时才有价值,否则对于您知道它的价值的图块没有附加价值切换。

【讨论】:

【参考方案3】:

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

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

但是如果你想指定最后一个参数(不是 nil),那么你必须提供一个闭包,它将 UIAlertAction 作为参数并且什么都不返回(Void)。参考您的链接,他只是使用他为简单起见创建的“警报”常量。

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

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

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

你不应该得到错误。

3) UIAlertAction 只有(我相信)一个 init 方法,因此您需要提供所有三个参数来创建它。请参阅我的 1) 样式答案:.default。这是一种调用 Swift 枚举的新方法。顺便说一句,所有枚举都必须是小写的,所以 .default 不是 .Default`在此处输入代码

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

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

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

【讨论】:

1) 好的 2) 和我写的一样,还是错了。 3) 正确 4) 我不明白你的意思 你所说的常量“动作”是什么意思? 查看您添加的人的链接 创建一个常量 let alert = UIAlertViewController(.... 没有链接提到“常数”,如果您愿意分享,我将不胜感激。如果您的意思是 let 中的常量,那么您的答案中使用常量非常无关紧要。使用letvar 有区别吗?你也在谈论被捕获的上下文中的动作。因此,我再次感到困惑,您为什么要在关闭之前提及它。从您的答案中删除它不会降低您的答案的用处。

以上是关于你应该如何处理 UIAlertAction 的闭包参数的主要内容,如果未能解决你的问题,请参考以下文章

前端知识体系:JavaScript基础-作用域和闭包-如何处理循环的异步操作

老旧的API,你应该如何处理?

关于颠覆,我应该如何处理供应商目录?

Python 函数如何处理你传入的参数类型?

如何处理错误的数据类型输入

如何处理不同语言的 iOS 推送通知