Swift - 可选参数未按预期工作
Swift - optional parameter not working as expected
我有一个方法可以迭代类别 class 的列表,最后从所有类别中迭代 return 项。
简单的代码如下所示:
func iterateMyCategoriesItems(item:(_ category:Category) -> Void)
{
for category in allCategories
{
item(category)
}
}
使用时:
iterateMyCategoriesItems { (category) in
// doing something here with every category...
}
到目前为止一切顺利,但现在我想为此方法添加一个可选的完成,所以我将代码更改为:
func iterateMyCategoriesItems(item:(_ category:Category) -> Void, _ completion:(() -> Void)? = nil)
{
for category in allCategories
{
item(category)
}
completion?()
}
但是现在当我尝试使用这样的方法时:
iterateMyCategoriesItems { (category) in
// doing something here with every category...
}
编译器显示错误:
Missing argument for parameter 'item' in call.
所以,我做错了什么?
当您在函数末尾使用尾随 {}
时,编译器会自动将其分配给函数的最后一个参数(完成闭包),因此它认为缺少 items 参数你的电话
你可以这样使用它:
iterateMyCategoriesItems (items:{ (category) in
// doing something here with every category...
})
或者如果你想完成
iterateMyCategoriesItems (items: { (category) in
// doing something here with every category...
}) { _ in
//do things when completed
}
您应该能够确定您在此调用中使用了尾随闭包:
iterateMyCategoriesItems { (category) in
// doing something here with every category...
}
Swift 编译器检测到这是一个尾随闭包,因此它将它与方法的最后一个参数(完成处理程序)匹配。
现在它已经完成了,它将继续寻找与第一个参数匹配的其他参数。 None 被发现所以它抱怨。
要解决此问题,您必须放弃使用尾随闭包并正确传递参数:
iterateMyCategoriesItems(items: { (category) in
// doing something here with every category...
})
您也可以删除参数标签以使其更清晰。
Swift book describes the Trailing Closure如下:
If you need to pass a closure expression to a function as the
function’s final argument and the closure expression is long, it
can be useful to write it as a trailing closure instead.
(添加了粗体。)
它清楚地将目标参数定位为 final。
即使最后一个参数是可选的,这条规则似乎也适用。
//-> warning: closure parameter prior to parameters with default arguments will not be treated as a trailing closure
func iterateMyCategoriesItems(item:(_ category:Category) -> Void, _ someOptionalIntParam: Int? = nil)
{
for category in allCategories
{
item(category)
}
}
//-> error: missing argument for parameter 'item' in call
iterateMyCategoriesItems { (category) in
// doing something here with every category...
}
如其他答案中所述,如果您想保持函数定义不变:
func iterateMyCategoriesItems(item:(_ category:Category) -> Void, _ completion:(() -> Void)? = nil)
{
for category in allCategories
{
item(category)
}
completion?()
}
(这是另一个话题,但是如果你想写一个没有参数的闭包类型,你应该避免(Void)->Void
。参见。)
你需要这样称呼它:
iterateMyCategoriesItems(item: { (category) in
// doing something here with every category...
})
如果你想写 item
闭包总是作为尾随闭包,你可以像这样修改你的函数定义:
func iterateMyCategoriesItems(completion:(() -> Void)? = nil, item:(_ category:Category) -> Void)
{
for category in allCategories
{
item(category)
}
completion?()
}
//Does not cause error
iterateMyCategoriesItems { (category) in
// doing something here with every category...
}
但是,您可能不喜欢将 completion
闭包放在其他闭包之前。
我有一个方法可以迭代类别 class 的列表,最后从所有类别中迭代 return 项。 简单的代码如下所示:
func iterateMyCategoriesItems(item:(_ category:Category) -> Void)
{
for category in allCategories
{
item(category)
}
}
使用时:
iterateMyCategoriesItems { (category) in
// doing something here with every category...
}
到目前为止一切顺利,但现在我想为此方法添加一个可选的完成,所以我将代码更改为:
func iterateMyCategoriesItems(item:(_ category:Category) -> Void, _ completion:(() -> Void)? = nil)
{
for category in allCategories
{
item(category)
}
completion?()
}
但是现在当我尝试使用这样的方法时:
iterateMyCategoriesItems { (category) in
// doing something here with every category...
}
编译器显示错误:
Missing argument for parameter 'item' in call.
所以,我做错了什么?
当您在函数末尾使用尾随 {}
时,编译器会自动将其分配给函数的最后一个参数(完成闭包),因此它认为缺少 items 参数你的电话
你可以这样使用它:
iterateMyCategoriesItems (items:{ (category) in
// doing something here with every category...
})
或者如果你想完成
iterateMyCategoriesItems (items: { (category) in
// doing something here with every category...
}) { _ in
//do things when completed
}
您应该能够确定您在此调用中使用了尾随闭包:
iterateMyCategoriesItems { (category) in
// doing something here with every category...
}
Swift 编译器检测到这是一个尾随闭包,因此它将它与方法的最后一个参数(完成处理程序)匹配。
现在它已经完成了,它将继续寻找与第一个参数匹配的其他参数。 None 被发现所以它抱怨。
要解决此问题,您必须放弃使用尾随闭包并正确传递参数:
iterateMyCategoriesItems(items: { (category) in
// doing something here with every category...
})
您也可以删除参数标签以使其更清晰。
Swift book describes the Trailing Closure如下:
If you need to pass a closure expression to a function as the function’s final argument and the closure expression is long, it can be useful to write it as a trailing closure instead.
(添加了粗体。)
它清楚地将目标参数定位为 final。
即使最后一个参数是可选的,这条规则似乎也适用。
//-> warning: closure parameter prior to parameters with default arguments will not be treated as a trailing closure
func iterateMyCategoriesItems(item:(_ category:Category) -> Void, _ someOptionalIntParam: Int? = nil)
{
for category in allCategories
{
item(category)
}
}
//-> error: missing argument for parameter 'item' in call
iterateMyCategoriesItems { (category) in
// doing something here with every category...
}
如其他答案中所述,如果您想保持函数定义不变:
func iterateMyCategoriesItems(item:(_ category:Category) -> Void, _ completion:(() -> Void)? = nil)
{
for category in allCategories
{
item(category)
}
completion?()
}
(这是另一个话题,但是如果你想写一个没有参数的闭包类型,你应该避免(Void)->Void
。参见
你需要这样称呼它:
iterateMyCategoriesItems(item: { (category) in
// doing something here with every category...
})
如果你想写 item
闭包总是作为尾随闭包,你可以像这样修改你的函数定义:
func iterateMyCategoriesItems(completion:(() -> Void)? = nil, item:(_ category:Category) -> Void)
{
for category in allCategories
{
item(category)
}
completion?()
}
//Does not cause error
iterateMyCategoriesItems { (category) in
// doing something here with every category...
}
但是,您可能不喜欢将 completion
闭包放在其他闭包之前。