阻止回调或协议,以在 VIPER 中的 DataManager 和交互器之间传递信息



使用 Objective-C 时,这是在使用VIPER架构模式时将对象从DataManager传递到Interactor的首选方法。

特别是使用Block Based CallbacksDataManager Output Protocol

VIPER 上原始互助移动文章中的示例待办事项应用程序

这样使用Block Based Callbacks

- (void)todoItemsBetweenStartDate:(NSDate *)startDate endDate:(NSDate *)endDate completionBlock:(void (^)(NSArray *todoItems))completionBlock;

而旅工程的这种方法

利用DataManager上的OutputProtocol

[self.interactor foundUser:user];

哪种方法更好,为什么?

注意:我知道在使用 Swift 时,闭包可以使回调方法更加干净。这个问题直接参考了Objective-C。

如果可能的话,我倾向于使用输出协议,因为它使测试更容易。当只有一个侦听器时,使用输出协议更容易。如果有多个侦听器,则使用回调块会更容易,这样对象就不必为每个请求跟踪接收方。

我发现输出协议更容易测试,因为您可以直接调用侦听器。例如,表示器通常实现交互器的输出协议。假设我们的登录交互器输出协议有两种方法:

- (void)didLogin - (void)loginFailedWithError:(NSError*)error

在测试登录

演示器时,我们需要编写有关登录成功和登录失败的测试。成功登录测试可以直接调用[presenter didLogin];,失败测试可以直接调用[presenter loginFailedWithError:badCredentialsError];

相反,如果我们使用了回调块,则登录交互器接口可能如下所示:

- (void)loginWithUsername:(NSString*)username password:(NSString*)password result:(void (^)(NSError* error))block;

测试演示器

时,若要测试成功案例,需要存根交互器登录方法以返回成功,然后在演示器上调用一个方法,该方法将强制它向交互器发出登录请求。

[interactor willSucceed]; [presenter login];

这使您的测试不太清楚实际意图。

如果可以设计数据管理器 API 以支持输出协议,这将使测试更容易。如果没有,我不会担心它,只需使用回调块。

这不是一刀切的,而是:

  1. 如果只有一个回调,则倾向于支持完成块。
  2. 如果存在一系列相关的回调,则倾向于支持协议/委托。

您可能还有其他启发式方法可以使用(例如,如果可能有一个明显的对象来实现协议并且只需要实现一次,则委派更好(。

你可以看到两者都在Apple的框架中使用。 在块之前,有更多的调用目标/选择器 - 我会说永远不要使用它(使用块代替(

最新更新