场景

今天,我想谈谈“场景”,我的名字是一个简单的结构,用于将View / ViewController / ViewModel集合的相关位收集在一起。 让我们通过看一个例子来开始,然后我们将逐步进行介绍。

  struct MenuScene:场景 
{
typealias依赖关系= HasAppBroker和HasStore
  typealias控制器= MenuViewController 
typealias视图= MenuView
typealias交互器= MenuInteractor
 让config = PresentationConfig.menu 
让控制器:控制器= MenuViewController()
让视图:视图
  init(有依赖关系:依赖关系) 
{
self.view = self.controller.menuView
  Interactor.configureBindings(场景:自我, 
依赖关系:依赖关系)
}
}

它符合具有一些关联类型Scene协议-ControllerViewInteractor ,并且如您在init的最后一部分所看到的那样, interactor具有某些依赖性。 插入器只是具有单个暴露的静态函数configureBindings的结构的名称。

依赖关系是通过一系列协议创建的,每个协议一个。 在这种情况下,为HasAppBrokerHasStore

 协议HasAppBroker { 
var appBroker:AppBroker {获取}
}
 协议HasStore { 
var store:存储{get}
}

我们将它们组合在一起以创建Dependencies类型。 然后,只要我们发布到场景init中的所有内容都符合那些协议,就可以满足相关性。

视图设置为我们要处理的主视图; 在这种情况下,我们使用子视图。 我们还有一个配置结构,表示为每个场景设置的演示文稿配置(例如:显示/隐藏工具栏)。

如果需要ViewModel或类似的视图,也可以在此处设置。

就是这样……那么这给我们带来了什么?

第一个好处是它将视图机制的所有部分组合在一起,并提供了一个单一的位置,可以在该位置调用视图,视图控制器和视图模型上的绑定或其他配置,并通过将其自身传递给配置函数来简化此配置(以及与任何依赖项)。

要了解第二个好处,我们需要查看Scene协议和相关的结构AnyScene

 协议场景 
{
relatedtype控制器:UIViewController
关联类型视图:UIView
  var config:PresentationConfig.Type {get} 
var控制器:控制器{get}
var视图:查看{get}
}
 扩展场景 
{
func toAnyScene()-> AnyScene
{
返回AnyScene(config:self.config,
控制器:self.controller,
查看:self.view)
}
}
 结构AnyScene 
{
var config:PresentationConfig.Type
var控制器:UIViewController
变数检视:UIView
  init(config:PresentationConfig.Type, 
控制器:UIViewController,
视图:UIView)
{
self.config =配置
self.controller =控制器
self.view =视图
}
}

AnyScene是系统的心脏; 在我的情况下,场景与应用程序状态相关联-每个状态都有一个场景。 场景中的relatedtype s意味着我们不必在场景结构中将UIViewController强制转换为例如: MenuViewController ,我们可以使用它。 现在,当状态更改时,应用程序将获取关联的场景,将其转换为AnyScene并将其传递给导航控制器以替换现有状态。 AnyScene具有导航控制器呈现该场景所需的一切,但至关重要的是,不再绑定到Scene协议的关联类型 。 因此可以在不与泛型混淆的情况下使用! 这是一种类型擦除的方法。 这具有额外的好处,例如,我们可以拥有AnyScene数组,这对于键入的场景是不可能的。