阻止回调或协议在VIPER中的DataManager和Interactor之间传递信息?

时间:2016-02-09 13:52:07

标签: ios objective-c architecture viper-architecture

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

特别使用Block Based CallbacksDataManager Output Protocol

Sample To Do App

中的Original Mutual Mobile article on VIPER

像这样使用Block Based Callbacks

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

来自Brigade Engineering的this approach

利用OutputProtocol

上的DataManager

[self.interactor foundUser:user];

哪种方法更好,为什么?

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

2 个答案:

答案 0 :(得分:3)

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

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

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

在测试Login Presenter时,我们将要在登录成功和登录失败时编写测试。成功登录的测试可以直接调用[presenter didLogin];,失败测试可以直接调用[presenter loginFailedWithError:badCredentialsError];

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

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

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

[interactor willSucceed]; [presenter login];

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

如果您可以设计DataManager API以支持输出协议,那么它将使测试更容易。如果没有,我不会担心它,只需使用回调块。

答案 1 :(得分:1)

这不是切割和干燥,但是:

  1. 如果只有一个回调,则倾向于支持完成块。
  2. 如果存在相关回调系列,则倾向于支持协议/授权。
  3. 您可以使用其他启发式方法(例如,如果可能有明显的对象来实现协议,则委派会更好,而且只需要实现一次)。

    您会看到Apple的框架中都使用了这两种方法。在块之前,有更多的目标/选择器调用 - 我会说永远不会使用它(使用块代替)