嵌套闭包不喜欢参数列表

11

一个UIView需要根据自定义控件的完成处理程序更改警告标签:

    voucherInputView.completionHandler = {[weak self] (success: Bool) -> Void in

        self?.proceedButton.enabled = success
        self?.warningLabel.alpha = 1.0

        if success
        {
            self?.warningLabel.text = "Code you entered is correct"
            self?.warningLabel.backgroundColor = UIColor.greenColor()
        }
        else
        {
            self?.warningLabel.text = "Code you entered is incorrect"
            self?.warningLabel.backgroundColor = UIColor.orangeColor()
        }


        UIView.animateWithDuration(NSTimeInterval(1.0), animations:{ ()-> Void in
            self?.warningLabel.alpha = 1.0
        })

最后的动画块显示表单中的错误。

Cannot invoke 'animateWithDuration' with an argument list of type '(NSTimeInterval), animations: ()-> Void)'

如果我在完成闭包之外的某个地方调用它,它就可以工作。

2个回答

39

问题在于闭包隐式地返回了这个表达式的结果:

self?.warningLabel.alpha = 1.0

但闭包本身被声明为返回 Void

添加显式的 return 应该可以解决这个问题:

UIView.animateWithDuration(NSTimeInterval(1.0), animations: { ()-> Void in
    self?.warningLabel.alpha = 1.0
    return
})

5
这对我来说解决了问题,但有人能否解释一下为什么这种行为对许多人来说如此奇怪和意外?顺便说一句,在您的示例中,您可以将()->Void替换为_,并使用; return将返回附加到同一行。此外,您可以写;()而不是单行return。 :) - BastiBen
1
@badcat 当你编写一个没有 return 关键字的闭包时,闭包会自动返回最后一个语句。这样做是为了让 array.sort {$0.index < $1.index} 起作用。如果你的最后一个语句是可选类型的赋值,它将返回 Void?。如果你让 Xcode 推断类型,你可以看到这一点:() -> ()?。空的 return 语句隐式地返回 Void(非可选类型)。有趣的事实是:Void(), 空元组的别名,如果你不输入 return 语句,所有函数都会返回它。(1/2) - vrwim
1
函数可以处理可选的Void作为最后一行的结果,因为它们不需要猜测任何返回值。所有的返回值都必须是明确的。 - vrwim
@badcat 写代码时,为什么要在return后面加;或者();?总体而言,加上; return比单纯的return需要输入更多字符吗?如果Antonio能回答就更好了。提前感谢。 - Unheilig
1
@Unheilig:你可以将闭包写在一行中 - 在这种情况下,这两个语句必须分开:self?.warningLabel.alpha = 1.0; return - Antonio
@Antonio 现在我明白了,您回复之前我已经点赞了。谢谢。 - Unheilig

0

Antonio的解决方案也适用于嵌套闭包,比如在UITableViewRowAction处理程序中执行AFNetworking请求。

override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]? {

    let cleanRowAction = UITableViewRowAction(style: UITableViewRowActionStyle.Default, title: "Do Stuff", handler: {[weak self](action: UITableViewRowAction!, indexPath: NSIndexPath!) in

        AFHTTPSessionManager(baseURL: NSURL(string: "http://baseurl")).PUT("/api/", parameters: nil, success: { (task: NSURLSessionDataTask!, response: AnyObject!) -> Void in

                // Handle success

                self?.endEditing()
                return
            }, failure: { (task: NSURLSessionDataTask!, error: NSError!) -> Void in

                // Handle error

                self?.endEditing()
                return
        })
        return

    })

    cleanRowAction.backgroundColor = UIColor.greenColor()
    return [cleanRowAction]
}

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