你应该如何处理 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
中的常量,那么您的答案中使用常量非常无关紧要。使用let
或var
有区别吗?你也在谈论被捕获的上下文中的动作。因此,我再次感到困惑,您为什么要在关闭之前提及它。从您的答案中删除它不会降低您的答案的用处。以上是关于你应该如何处理 UIAlertAction 的闭包参数的主要内容,如果未能解决你的问题,请参考以下文章