SwiftFlow 0.2.2

SwiftFlow 0.2.2

测试已测试
Lang语言 SwiftSwift
许可证 MIT
发布上次发布2016年1月
SPM支持 SPM

Benjamin Encz 维护。



SwiftFlow 0.2.2

相关项目

如果您 landed 在这里,您还应该看看在 ReduxKit 上的出色工作,它将原始的 Redux API 带到 Swift。我们一致认为,协作和分享想法将有利于这两个项目。去看看。对这两个项目的反馈将会受到赞赏。

目录

关于 Swift Flow

此库为预发行版本。预期文档不全和 API 破坏性更改。

Swift Flow 是在 Swift 中实现单向数据流架构的库,类似于 Redux。它采用单向数据流,只允许变更状态通过声明式动作。

它依赖以下几个原则

  • Store 存储整个应用程序状态,形式为单个数据结构。该状态只能通过向 Store 分发动作进行更改。每当 Store 中的状态发生变化时,Store 将通知所有观察者。
  • Actions 是描述状态变化的声明性方式。动作不包含任何代码,它们被 Store 消费,并转发给 Reducers。通过实现不同的状态变化以响应每个动作,Reducers 将处理动作。
  • Reducers 提供纯函数,根据当前动作和当前应用程序状态创建新的应用程序状态。

对于一个非常简单的应用程序,例如维护一个可以递增和递减的计数器,您可以定义以下应用程序状态:

struct AppState: StateType {
    var counter: Int = 0
}

您也会定义两个动作,一个用于增加计数器,一个用于减少计数器。在 入门指南 中,您可以了解如何构造复杂动作。对于本例中的简单动作,我们可以定义空的结构体,使其符合动作协议

struct CounterActionIncrease: Action {}
struct CounterActionDecrease: Action {}

您的 Reducer 需要响应这些不同的动作类型,可以通过在动作类型上切换来实现

struct CounterReducer: Reducer {

    func handleAction(var state: AppState, action: Action) -> AppState {
        switch action {
        case _ as CounterActionIncrease:
            state.counter += 1
        case _ as CounterActionDecrease:
            state.counter -= 1
        default:
            break
        }

        return state
    }

}

为了有一个可预测的应用程序状态,重要的是 Reducer 总是纯函数,它接收当前应用程序状态和动作,并返回新的应用程序状态。

最后,您的视图层(在这种情况下是一个视图控制器)需要通过订阅 Store 更新并发出动作,在应用程序状态需要更改时连接到这个系统

class CounterViewController: UIViewController, StoreSubscriber {

    @IBOutlet var counterLabel: UILabel!

    override func viewWillAppear(animated: Bool) {
        mainStore.subscribe(self)
    }

    override func viewWillDisappear(animated: Bool) {
        mainStore.unsubscribe(self)
    }

    func newState(state: AppState) {
        counterLabel.text = "\(state.counter)"
    }

    @IBAction func increaseButtonTapped(sender: UIButton) {
        mainStore.dispatch(
            CounterActionIncrease()
        )
    }

    @IBAction func decreaseButtonTapped(sender: UIButton) {
        mainStore.dispatch(
            CounterActionDecrease()
        )
    }

}

每当有新的应用状态可用时,newState 方法将被 Store 调用,这是我们需要调整视图以反映最新应用状态的地方。

按钮点击会导致被分发的操作,这些操作将由存储和其还原器处理,从而产生新的应用状态。

这是一个非常基础的示例,仅展示了 Swift Flow 的部分功能,阅读入门指南以了解您如何使用该架构构建整个应用。

为什么选择 Swift Flow?

模型-视图-控制器 (MVC) 不是一个完整的应⽤架构。典型的 Cocoa 应用将很多复杂性委托给控制器,因为 MVC 没有提供其他的状态管理等复杂的解决方案,这是应用开发中最复杂的问题之一。

建立在 MVC 之上的应用通常会带有大量的状态管理和传播的复杂性。我们需要在应用中使用回调、代表、键值观察和通知来传递信息,并确保所有相关的视图都有最新的状态。

这种方法涉及大量的手动步骤,因此容易出错,而且在复杂的代码库中扩展性不好。

这也会导致代码难以一眼看出,因为依赖项可能隐藏在视图控制器深处。最后,你还会得到不一致的代码,因为不同的开发者会使用他们各自偏好的状态传播过程。你可以通过风格指南和代码审查来规避这个问题,但你不能自动验证是否符合这些指南。

Swift Flow 通过对应用程序编写方式施加严格的约束来试图解决这些问题。这减少了程序员犯错误的余地,并导致易于理解的应用程序 - 通过检查应用程序状态数据结构、操作和还原器。

该架构除了改进代码库之外,还提供了其他好处

  • 存储、还原器、操作以及像 Swift Flow Router 这样的扩展完全不受平台限制 - 你可以轻松使用相同的企业逻辑,并在多个平台上(iOS、tvOS 等)共享它们。
  • 想要与同事协作修复应用崩溃吗?使用 Swift Flow Recorder 记录导致崩溃的操作,并发送 JSON 文件供他们重放操作并立即重现问题。
  • 也许记录的操作可以用来构建 UI 和集成测试?

Swift Flow 工具仍然处于非常早期的阶段,但上述前景让我很兴奋,也许社区中的其他人也是如此!

入门指南

描述使用 Swift Flow 构建的应用核心组件的入门指南在这里:[A Getting Started Guide](https://raw.github.com/Swift-Flow/Swift-Flow/0.2.2/Readme/GettingStarted.md)。它将在接下来的几周内扩展。为了理解核心原则,我建议您阅读出色的 [Redux 文档](http://rackt.org/redux/)。

安装

检出源代码和运行测试

由于 Nimble 存在 一个问题,此时,如果你从源代码构建 Nimble / Quick,tvOS 测试将失败。但是,你可以从二进制安装 Nimble & Quick,然后仅重新构建 OSX & iOS。检出后,请在终端中运行以下命令

carthage bootstrap && carthage bootstrap --no-use-binaries --platform ios,osx

示例

使用这个库,你可以实现有显式、可重复的状态的应用程序,这使你能够重放和倒转应用状态,如下所示

扩展

本仓库包含Swift Flow的核心组件,以下是一些扩展:

  • Swift-Flow-Router:提供一个与SwiftFlow兼容的路由器,允许iOS应用程序进行声明式路由
  • Swift-Flow-Recorder:提供了一种Store实现,记录所有Action,并支持热重载和时间旅行

示例项目

  • CounterExample:一个使用Swift Flow实现非常简单的计数应用。这个应用也展示了使用SwiftFlowRouter的基本路由。
  • Meet:一个用Swift Flow构建的实战应用,目前还处于非常早期阶段。

贡献

这里还有很多工作要做!我非常希望你能参与进来!Swift Flow的核心仍有一些设计决策悬而未决(见问题),还有很多有用的文档可以编写,以及大量的扩展和工具等待在Swift Flow之上构建。

我认为开始为这个库做贡献的最好的方法是将其用于你的项目中!

致谢

  • 非常感谢Dan Abramov构建Redux - 这里的所有想法以及许多实现细节都是由他的库提供的。

联系方式

如果您有任何问题,可以在twitter上找到我:@benjaminencz