苹果手表架构

去年12月,我们发布了FanDuel Apple Watch应用程序,为玩家提供了一种快速简便的方法来检查他们的阵容在移动中的表现。 创建应用程序给我们带来了许多有趣的挑战,包括如何干净地设计应用程序。

我们练习了测试驱动的开发(TDD),并允许这种方法来驱动体系结构。 事后看来,我们当时做出的某些决定变得更加容易,但我认为准确地安排思考过程是很有用的。

我们从解决与iOS应用程序最不通用的区域开始; 手表和手机之间的消息传递。 尽管watchOS 2可以直接在手表上编写网络代码,但我们无法利用这一点。 我们的iOS应用程序的联网部分相当复杂,并且向用户(尤其是那些玩实况游戏的用户)发送数据是一项时间紧迫的操作,因此,利用我们已经在电话上拥有的联网堆栈更加有意义。

然后,我们研究了实时消息传递,以及当用户打开手表应用程序或查看Glance时是否发送网络请求以下载用户的最新数据。 为此,我们发现watchOS 2中的WCSession类引入的实时消息传递功能非常适合。 此外,由于我们必须包装WCSession并为其提供委托,因此有必要创建一个类坐在它与应用程序的其余部分之间。 在电话上,我们创建了WatchConnector类,在手表上,我们创建了PhoneConnector类作为其相反的数字。 这些类的功能非常相似。 他们通过充当代表从WCSession接收消息,并在收到指示时将消息发送到WCSession。

一旦我们对如何构造两个设备之间的通信有了一个大致的了解,就该开始着眼于将它们与watch应用程序中的屏幕连接起来了。 对于实际的屏幕架构,我们能够从FanDuel手机应用程序中大量借用。 基本上,这意味着将所有表示逻辑从UIViewControllers引入Presenters,并将所有业务逻辑从ViewControllers和Presenters引入Interactors。 看起来类似于以下内容:

由于watch应用程序需要绝对最少的设备上业务逻辑,因此我们决定在Presenter层和Interactor层之间插入消息传递机制,并有效地使用上述架构,但是会在两个设备之间传播。

此时,实际上只剩下两个问题需要回答:

  • 演示者如何告诉我们的连接器发送消息?
  • 我们的连接器如何通知演示者他们收到了他们感兴趣的消息?

(当然,这是在电话端镜像的,交互器与连接器通信,反之亦然)。 我们决定在Presenters和Connector之间包括一个Requester类,该类将接收来自Presenter的事件信息,并将其转换为请求消息,以供Connector发送到电话。 同样,我们决定在电话上开设一个名为Responder的类,该类负责获取请求消息的主体并将其路由到用于网络和业务逻辑的正确Interactor。

从理论上讲,既然我们可以有多个请求者一次请求数据,或者有多个响应者同时返回数据,但是每边只有一个WCSession,那么这似乎是实现观察者模式的理想场所。 也就是说,请求者将注册为PhoneConnector的观察者,该观察者将在收到消息时通知他们,从而允许他们在必要时采取措施。 这就是我们最终的架构,如下所示:

对于我们的FanDuel Apple Watch应用程序来说,这感觉像是一种非常灵活且明智的体系结构,尤其是考虑到我们遇到并克服的最初挑战。 总体而言,这是一个相当干净的体系结构,其中每个部分都有明确定义的单一职责,并且可以轻松地进行隔离测试。 我敢肯定,还有待进一步改进,我迫不及待地想要进行更多的实验。

Matthew Healy,iOS工程师和Scrum Master