Swift完成块

8
我很难理解我遇到的问题。 为了简化,我将使用UIView方法。 基本上,如果我编写该方法
UIView.animateWithDuration(1, animations:  {() in
        }, completion:{(Bool)  in
            println("test")
    })

它正常工作。现在,如果我使用相同的方法,但是创建一个字符串,像这样:
    UIView.animateWithDuration(1, animations:  {() in
        }, completion:{(Bool)  in
            String(23)
    })

它停止工作了。编译器错误:调用中缺少参数“delay”
现在,这里有个奇怪的部分。如果我使用与失败的代码完全相同的代码,但只是添加一个打印命令,就像这样:
   UIView.animateWithDuration(1, animations:  {() in
        }, completion:{(Bool)  in
            String(23)
            println("test")
    })

它又开始工作了。
我的问题基本上是相同的。我的代码:
   downloadImage(filePath, url: url) { () -> Void in
         self.delegate?.imageDownloader(self, posterPath: posterPath)
        }

不起作用。但如果我改成。
 downloadImage(filePath, url: url) { () -> Void in
             self.delegate?.imageDownloader(self, posterPath: posterPath)
                println("test")
            }

甚至可能是:
downloadImage(filePath, url: url) { () -> Void in
             self.delegate?.imageDownloader(self, posterPath: posterPath)
             self.delegate?.imageDownloader(self, posterPath: posterPath)
            }

它的工作正常。 我不明白为什么会发生这种情况。我快要接受这是编译器的一个错误了。
1个回答

11

Swift中的闭包在仅由单个表达式组成时具有隐式返回值。这使得代码更加简洁,例如:

reversed = sorted(names, { s1, s2 in s1 > s2 } )

在您的情况下,当您在此处创建字符串时:

UIView.animateWithDuration(1, animations:  {() in }, completion:{(Bool) in
    String(23)
})

你最终返回了那个字符串,这使得你闭包的签名为:

(Bool) -> String

这已经不符合animateWithDuration的要求(这会转化为Swift中晦涩的Missing argument for parameter 'delay' in call错误,因为它找不到匹配的函数签名)。

一个简单的解决方法是在闭包结尾添加一个空的return语句:

UIView.animateWithDuration(1, animations:  {() in}, completion:{(Bool) in
    String(23)
    return
})

这会让您的签名变得更加符合期望:

(Bool) -> ()

你的最后一个例子:

downloadImage(filePath, url: url) { () -> Void in
    self.delegate?.imageDownloader(self, posterPath: posterPath)
    self.delegate?.imageDownloader(self, posterPath: posterPath)
}

这个方法之所以起作用是因为它包含了两个表达式,而不仅仅是一个;当闭包只包含单个表达式时,隐式返回才会发生。因此,该闭包没有返回任何内容,并且与其签名相匹配。


谢谢。但是如果我添加String(23)并再次复制相同的行,为什么它不会失败? - Wak
我实际上正在回答中澄清这个问题。请查看编辑。 - Mike S
谢谢您的回答,帮助我找出了为什么出现一个奇怪的“不能调用'type'类型的参数列表的'animateWithDuration'”错误。结果发现修复方法完全相同。 - SonarJetLens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接