LassoTestUtilities 1.6.0

LassoTestUtilities 1.6.0

Steven GrosmarkSteven GrosmarkSteven Grosmark维护。



  • Steven Grosmark和Trevor Beasty提供

Lasso logo

Lasso是一个iOS应用程序架构,用于构建离散、可组合、可测试的组件,从单个屏幕到复杂的流程,再到高级应用结构。

为什么选择Lasso?

如果没有一套结构化的原则,应用程序的代码库很容易变得难以推理和维护。特别是,这些问题最终会出现

  • 组件之间的紧密耦合使得更改/测试变得困难
  • 业务逻辑分散在奇怪的地方,使得修改/重用/调试/测试现有代码变得困难
  • 在不当的地方做出的视图表示选择,使得重构/重新组织/测试流程变得困难
  • 团队间组织不一致,使得交叉协作困难

Lasso方法

Lasso鼓励强大的关注点分离,通过清楚地定义拥有单独责任的单个组件,指出特定类型的代码应该存放的位置,并提供清晰的、灵活的组件间通信方式。较大的行为单元可以轻松地组合和重新组合。

屏幕

我们通常将屏幕视为应用程序中单个页面/视图,例如登录视图、联系人列表视图、音频设置视图等。

在Lasso中,Screen是用来实现单个视图的类型集合

Diagram of a Screen and its constituent parts

View(即UIViewController)负责:

  • 精确渲染屏幕当前的State(即内容)
  • 将用户交互传递给Store(即决策者)
  • 响应用户状态的变化以保持界面是最新的

Lasso视图通常很小,其中基本没有逻辑。

使用单向数据流来确保一致性:视图绝不会直接响应用户操作而重新渲染任何内容。视图将Actions发送到Store,更新State,然后将状态变更通知作为State发送回视图。

Store是屏幕决策的地方,是屏幕State的真相来源。一个Store负责:

  • 屏幕的所有业务逻辑
  • 响应Actions(即从视图发送的事件)
  • 更新屏幕的State

当发生更合适在其他地方处理的事件时,Store也可以生成一个Output。例如,登录屏幕可能会生成一个“用户已登录”的输出,作为信号给高级系统转移到应用程序的登录部分;或者,联系列表屏幕可能会生成一个“选中联系人”的输出,作为信号给高级流程以显示或推送一个联系人详情界面。

流程

Flow代表应用程序的功能或区域,通常由一系列Screen组成。例如,“新用户”流程可能由一系列一次性信息屏幕和一个单独的“让我们开始”屏幕组成。

Diagram of a Flow

Flow在一个视图层的合适上下文中实例化和开始(例如,“注册”流程可能在一个菜单屏幕上展示,或者“欢迎”流程可能被推送到导航堆栈)。Flow首先创建其初始Screen,并监听Output信号。随着Output的到来,《code>Flow决定如何处理它们——它可以创建另一个Screen并将其放入视图层级,发出自己的Output(当发生更合适在其他地方处理的操作时),或者对Flow适当的任何事物。

由于ScreenFlow是封装的模块,具有离散的输入和输出点,因此在Flow中管理和处理Screen以及Flow相当常见且简单。这样,可以将应用程序定义为组件的层次结构,从顶层开始减少复杂性。

Diagram of a Flow within another Flow

示例应用

运行示例项目

  1. 克隆 Lasso 仓库
  2. Example 目录运行 pod install
  3. 打开 Lasso.xcworkspace

了解更多

需求

Lasso 支持 iOS 13 及以上版本,可使用 Swift 4.2 及以上版本编译

注意:Lasso v.1.3.0 已添加对 SwiftUI 的支持,最低部署目标为 iOS 13.0。如果您需要支持更早的 iOS 版本,请使用 v1.2.1。

安装

Cocoapods

Lasso核心框架添加到您的Podfile的主要目标中

Pod 'Lasso'

还要将LassoTestUtilities添加到您的测试目标(s)

Pod 'LassoTestUtilities'

Swift包管理器

Lasso包的网址是

`https://github.com/ww-tech/lasso.git`

有关示例用法,请参阅:Swift包管理器示例

Tuist

要将Lasso添加为tuistTargetDependency

  • 将此仓库克隆到喜欢的位置
  • 创建一个.project依赖项
  • 将依赖项添加到您的目标依赖项中
let lasso: TargetDependency = .project(target: "Lasso", path: "../../path-to-lasso-repo-clone/")

let demo = Target(
    name: "Demo",
    platform: .iOS,
    product: .framework,
    bundleId: "com.example.Demo",
    dependencies: [ lasso ]
)

还要将LassoTestUtilities添加到您的测试目标(s)

let lassoTestUtilities: TargetDependency = .project(target: "LassoTestUtilities", path: "../../path-to-lasso-repo-clone/")

let demoTests = Target(
    name: "DemoTests",
    platform: .iOS,
    product: .unitTests,
    bundleId: "com.example.DemoTests",
    dependencies: [ LassoTestUtilities ]
)

贡献

我们热衷于贡献!

如果您有一个想法的功能,或者发现了一个错误,最好的做法是

  1. 搜索问题,看看是否有人已经提出过!
  2. 创建一个新的问题,详细说明您想看到哪些改进。
  3. 如果您有代码更改的想法,那真是太好了!
    1. 将Lasso仓库Fork。
    2. 为您的功能更改创建一个分支。
    3. 打开一个PR!

作者

Steven GrosmarkTrevor Beasty、Yuichi Kuroda和WW iOS团队。

许可

Lasso是以Apache-2.0开源许可进行许可的。

您可以按照自己的意愿使用它。我们确实欢迎致谢,如果您在使用它的话,我们也很愿意听到您的意见!