使用Redux模式编写iOS应用程序

图片

最近,我比移动设备更多地参与了前端开发,并且遇到了一些我已经知道的非常有趣的设计模式,但是直到现在才真正进入它们。

但是现在所有这些都说得通了,在使用React的开发工作了几周之后,现在我无法回到原来的iOS开发方式。 我不会切换到用于开发移动应用程序的javascript(AKA React Native),但是这里是我学到的一些知识。

图片

回到iOS开发,我创建了一个新项目并开始探索ReSwift ,这是Swift中FluxRedux模式的实现。 它的工作非常简单,我多次克隆了JavaScript应用程序的体系结构,现在我有了一个全局状态,而我的控制器只是侦听此状态。 控制器本身由封装非常特定行为的各种表示组件组成。

图片

所有状态更改都在一个地方在reducer中进行 。 一种为子状态。 您可以在一处看到所有动作 。 不再需要网络代码或调用控制器,不再需要视图中的对象变异。 没有更多的意大利面代码。 只有一个状态 ,这是事实,然后,您的各种表示组件(我坚持要坚持)都订阅了该状态的不同部分并做出相应的反应。 对于强大的模型应用程序,这仅仅是最佳的架构。

举个例子。 以前,登录视图控制器充满了很多行代码,各种控制状态,错误处理等。...现在看起来像这样:(作为示例)

import UIKit import Base import ReSwift class LoginViewController: UIViewController { @IBOutlet var usernameField: UITextField! @IBOutlet var passwordField: UITextField! override func viewDidLoad() { super.viewDidLoad() store.subscribe(self) {state in state.usersState } } @IBAction func onLoginButton(_ sender: Any) { store.dispatch(AuthenticatePassword(username: usernameField.text!, password: passwordField.text!)) } @IBAction func onTwitterButton(_ sender: Any) { store.dispatch(AuthenticateTwitter()) } @IBAction func onFacebookButton(_ sender: Any) { store.dispatch(AuthenticateFacebook(from: self)) } } // MARK: - State management extension LoginViewController: StoreSubscriber { func newState(state: UsersState) { if let error = state.authState.error { presentError(error: error.type, viewController: self, completion: nil) } if let _ = state.getCurrentUser { self.dismiss(animated: true, completion: nil) } } } 

控制器和全局状态下的分派操作表示形式,这些操作实际上与网络配合使用或启动应用程序转换为新状态所需的各个部分。

一个动作可以触发另一个动作,这就是它对网络请求的处理方式,例如,您有一个FetchUser动作(id:字符串),并且在一个类似于SetUser的化简器中截取了一个动作(用户:User)。 在reducer中,您负责将新对象与当前状态合并/合并。

首先,您需要state ,我的示例将围绕User对象,所以state可能看起来像这样:

 struct UsersState { var users: [String: User] = [:] } 

您必须具有一个封装该用户对象的所有网络活动的文件。

 struct FetchUser: Action { init(user: String) { GETRequest(path: "users/\(user)").run { (response: APIResponse<UserJSON>) in store.dispatch(SetUser(user: response.object)) } } } 

请求完成后,它将立即调用另一个操作 ,该操作实际上为空,应该在UsersActions中引用它。 该动作描述了减速器改变状态所必须依靠的结果。

 struct SetUser: Action { let user: UserJSON? } 

最后,最重要的工作是在UsersReducer中完成的,您需要捕获该动作并根据其内容进行一些工作:

 func usersReducer(state: UsersState?, action: Action) -> UsersState { var state = state ?? initialUsersState() switch action { case let action as SetUser: if let user = action.user { state.users[user.id] = User(json: user) } default: break } return state } 

现在,所需要做的就是在控制器或视图中订阅/订阅状态,并在状态更改时提取必要的信息并获取新值!

 class UserViewController: UIViewController { var userId: String? { didSet { if let id = userId { store.dispatch(FetchUser(user: id)) } } } var user: User? { didSet { if let user = user { setupViewUser(user: user) } } } override func viewDidLoad() { super.viewDidLoad() store.subscribe(self) {state in state.usersState } } func setupViewUser(user: User) { //Do uour UI stuff. } } extension UserViewController: StoreSubscriber { func newState(state: UsersState) { self.user = state.users[userId!] } } 

但是,现在您应该看一下ReSwift示例,以加深了解,我计划使用这种设计模式发布一个开源应用程序(实际上是一个游戏)。 但就目前而言,代码显示了如何将它们一起工作的非常原始的想法。

在Glose书籍中,这仍然是一个非常早期的体系结构,但是我们不能等待使用该体系结构将应用程序投入生产。

我觉得使用这种模式开发应用程序将节省大量时间和精力。 它比笨拙的REST客户端要花更多的工作,因为在客户端状态中会有更多的逻辑,但是最终它将为您节省宝贵的调试时间。 您将能够在本地修改许多元素,并且控制器和视图之间将不再级联更改。 以备份顺序重现状态,对其进行存档,创建中间件等。应用程序数据流清晰,集中且简单。

Redux模式为应用程序增加了一些结构。 我从事纯MVC已有很长时间了,我相信您可以创建干净的代码库,但是您倾向于养成往往弊大于利的习惯。 您甚至可以更进一步,通过在单独的状态下控制用户界面(例如视图控制器,警报查看器,路由控制器)来完全实现Redux,但是我还没有实现所有这些。

而且测试...单元测试现在很容易实现,因为您需要进行的测试只是将输入的数据与全局状态中包含的数据进行比较,因此测试可以发送模拟操作,然后检查状态是否与您所匹配的内容相匹配。想要。

说真的,这就是未来。 Redux的未来是:)

Source: https://habr.com/ru/post/zh-CN464561/


All Articles