Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
不接受任何输入的Swift闭包_Swift - Fatal编程技术网

不接受任何输入的Swift闭包

不接受任何输入的Swift闭包,swift,Swift,下面的(工作)代码创建一个UIAlertAction,在按下ok按钮后调用函数foo() let action = UIAlertAction(title: "OK", style: .Default, handler: {action in self.foo()}) 我的问题是,为什么必须将行动传递给关闭 例如,这样的事情对我来说是有意义的,因为我们在闭包中根本不引用动作。我希望能写一些像这样的东西 { () in self.foo() } [this](){this->foo();

下面的(工作)代码创建一个UIAlertAction,在按下ok按钮后调用函数foo()

let action = UIAlertAction(title: "OK", style: .Default, handler: {action in self.foo()})
我的问题是,为什么必须将行动传递给关闭

例如,这样的事情对我来说是有意义的,因为我们在闭包中根本不引用动作。我希望能写一些像这样的东西

{ () in self.foo() }
[this](){this->foo();};

在C++中,我希望编写一些类似

的东西。
{ () in self.foo() }
[this](){this->foo();};

这是怎么回事?

如果编译器可以确定闭包的类型,则可以使用隐式返回和速记参数名称,从而声明闭包,如:

let sorted = [ 4, 3, 1, 40, 19 ].sort { $0 > $1 }
但是,如果编译器无法确定它,则需要声明参数以便确定

以您自己的代码为例:

class Bar {

  func foo() {
  }

  func foo( s: String ) {
  }

  func sample() {
    // this works
    let a = UIAlertAction(title: "a", style: .Default, handler: { self.foo($0.title) } )
    // this doesn't work
    let a = UIAlertAction(title: "a", style: .Default, handler: { self.foo() } )
  }
}
处理程序闭包的定义为((UIAlertAction!)->(Void))!,因此,它需要一个带有单个参数(推断为UIAlertAction类型)的闭包,但不返回任何内容

第一个示例之所以有效,是因为通过使用$0,您告诉编译器闭包实际上只有一个参数,并且由于最后一个调用是函数foo,它不返回任何内容,因此闭包有一个参数,并且不返回任何内容,因此编译器可以这样使用它

但是,第二种方法不起作用,因为即使foo不返回任何内容,也没有使用任何参数,因此编译器无法判断闭包是否有参数。对于编译器,闭包是:(Void)->(Void),这不是正确的类型

在这种情况下,如果您的foo函数或闭包定义不允许编译器检测闭包类型,那么ABakerSmith答案可能就是您需要的答案。您仍然需要声明参数,但忽略这些参数将是最好的做法:

let a = UIAlertAction(title: "a", style: .Default, handler: { _ in self.foo() } )

您可以使用下划线忽略传递给处理程序闭包的参数,从而使代码:

{ _ in self.foo() }
您也可以在其他情况下使用下划线忽略参数,
用于循环,例如:

for _ in 0..<5 {
    ...
}

for uu0..@ncerzo的答案是正确的-这只是澄清了几件事。与Swift中的其他内容一样,闭包也有一个类型,编译器在确认您传递的闭包类型与所需类型匹配之前不会编译。编译器尽其所能从上下文推断闭包的类型,但有时不能,它要求代码是特定的

您所说的闭包只是忽略传递的参数。一个非常简单的例子是如下所示的闭包:

let ignoreMe: Int -> Int = { _ in 42 }
无论传递给
ignoreMe
的参数是什么,它都会被忽略,返回的值将是
42
。所以你似乎在问为什么下划线是必要的。您希望改为写以下内容:

let ignoreMe: Int -> Int = { 42 }
问题是编译器无法将右侧的类型与左侧的类型匹配。闭包
{42}
被推断为具有类型
Void->Int
,而在左侧
ignoreMe
被声明为具有类型
Int->Int
。类型不匹配

这个错误是编译器告诉您的方式,“我本以为是
Int->Int
类型的闭包,但您似乎给了我
Void->Int
类型的闭包。请澄清您的意图。”

{in42}
中的下划线是如何提供澄清的。您告诉编译器,“是的,这个闭包将接受一个参数,但它将被忽略。您可以安全地推断它的类型为
Int->Int


要求澄清似乎是不必要的行李,但行李很轻
{42}
{in 42}
对编码者来说不是什么负担。而且好处是巨大的。对于左手边类型和右手边类型之间的每一个有意的不匹配,都必须有很多非有意的不匹配(也称为错误或bug)。这些非故意的不匹配必须在代码编译之前修复。

handler:{self.foo()}这不会使用“表达式类型在没有更多上下文的情况下是不明确的”进行编译,因此我的问题是。(Xcode 7.0 beta 6,如果有必要的话)我认为造成混淆的原因是处理程序中的名称“action”并不表示您正在定义的
UIAlertAction
,它表示调用处理程序时将传递该处理程序的参数。在C++中,你将编写代码> [A](Autoaction){ -> ->();}编译你的代码,并且可能是该问题的正确解决方案,但是它不回答“为什么我必须向关闭声明声明”(因为你仍然声明它,甚至没有名字)。我想我的答案是肯定的。如果你不介意的话,我会参考你的来编辑它,使它更完整。我同意,我的帖子没有完全回答OP的问题(我当时有点匆忙)。不过我不介意——我很高兴你写了一个更完整的答案:)