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

Block Callbacks or Protocols to pass information between DataManager and Interactor in VIPER?

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

特别是 Block Based CallbacksDataManager Output Protocol

的使用

Sample To Do App from the Original Mutual Mobile article on VIPER

像这样使用Block Based Callbacks

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

this approach 来自旅工程部

DataManager

上使用 OutputProtocol

[self.interactor foundUser:user];

哪种方法更好,为什么?

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

这不是一成不变的,而是:

  1. 如果只有一个回调,则倾向于支持完成块。
  2. 如果有相关回调家族,倾向于protocol/delegation。

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

Apple 的框架中都用到了。在块之前,有更多调用 target/selector - 我会说永远不要使用它(改为使用块)

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

我发现输出协议更容易测试,因为您可以直接调用侦听器。例如,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;

在测试 Presenter 时,为了测试成功案例,您需要将 Interactor 登录方法存根到 return 成功,然后在 Presenter 上调用一个方法,强制它发出登录请求给交互器。

[interactor willSucceed]; [presenter login];

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

如果您可以将 DataManager API 设计为支持输出协议,这将使测试更加容易。如果没有,我也不担心,直接使用回调块。