TinyExtension:简化的空闭包

此文章同时提供中文版本: TinyExtension:空封闭简化

在Swift中,我们经常使用Closure。 当然,大多数Closure用于实现特定的功能块,但是在某些情况下,我们将使用空Closure:

情况1:忽略回调

通常,将实现回调方法,但有时接口提供的功能比我们需要的更多。 例如,我们需要使用以下功能:

func sampleRequest(success: (Bool, String) -> (), failure: () -> ()) { 
// some network request logic
// with some local variable store logic
}

通常,我们将实现successfailure回调,但是在某些情况下,我们将忽略某些回调。 例如,在预加载数据时,我们不需要处理failure回调。 毕竟,预加载是在后台调用的,错误消息永远不会响应UI,因此可以删除。 我们调用的代码如下:

 sampleRequest(success: { (isSuccess, text) in 
// do some complex thing
}, failure: {})

在这里,我们使用了空的Closure。 实际上,这很简单,因为failure回调不携带任何数据。 但是,如果我们的预加载在方法中完成,则也无需实现success回调,调用的效果将变为:

 sampleRequest(success: { _, _ in }, failure: {}) 

此时,空的Closure变得不那么简单了。 我们必须根据实际参数数量声明_ ,以忽略返回的数据。 如果将来回调参数的数量发生变化,我们还需要手动维护此空Closure。

有人可能会说我们可以在sampleRequest()使用默认回调为nil的可选回调来实现忽略回调的效果,但是我们需要处理更多可选内容,在某些情况下,我们无法修改实现代码,例如第三方图书馆。

情况2:使用闭包替换委托

就像在我们仍然使用Objective-C时,UIKit添加了块回调来替换简单的委托一样。 在Swift中,由于Closure比Objective-C块更易于使用,因此我们更频繁地使用Closure回调来实现简单的委托效果。 例如我有三个可点击的按钮。 需要通知其他对象,我们可以在不使用委托方法的情况下声明三个Closure对象:

 Class A { 
var didTapButtonA: () -> () = {}
var didTapButtonB: (Int, URL?) -> () = { _, _ in }
var didTapButtonC: (Int, Int, Int, Int, URL?) -> () = { _, _, _, _, _ in }
}

然后在触发按钮时应调用相应的Closure,需要获取通知的对象可以实现此属性,如下所示:

 let a = A() 
a.didTapButtonA = {
// some logic code
}

但是,我们可以看到didTapButtonBdidTapButtonC非常麻烦。 问题在于我们需要匹配参数数量以实现空的闭包,并且随后的更新也需要同步更新。 同样,我们可以使用可选类型,并将默认值替换为nil ,但我们应尽可能避免使用可选类型。