及时是盖MVC架构没有供状态管理的化解方案。也可作为是挪端应用开发)的架构演变史。

这是因为MVC架构没有提供状态管理的解决方案,也可以看成是移动端应用开发)的架构演变历史

Model-View-Controller (MVC)
对于iOS开发者来说不是一个周到的化解方案,常见的问题是最为多之模块(如网,业务和贮等)都于堆放在Controller中,对于页面包含多个状态的场面更是明确,如跳1000代码的Controller比比皆是,这是盖MVC架构没有供状态管理的解决方案。

由于没历史包袱,且团队愿意尝试一些不同的方案,经过简单健全专注的习及调研以后,我们并没采取主流的
MVVM 架构,而是因 ReSwift 以及 Swift 这宗语言的性状(核心是
extension)构建了同样模仿类似 Vue + Vuex
的方案,笔者打算经四首文章来划分享下这种思路。

至于iOS 常见架构一览参见这里。

亟待专注的是,笔者为是首先糟接触 Swift 和 iOS,某种程度上来说,也是一致称
iOS 菜鸟,行文中难免出现无高明之远在,还为指正。但又,笔者也发 Scala
和多年底 Web
前端开发经历,不同之平台以及言语,会产生一般的构思以及文化结构,所以入门移动端原生应用开发时,也意识众多共同之处。

对冲MVC的复杂性逻辑页面,我们用手动地运回调(callbacks),委托(delegations),KVO(Key-Value-Observation)和通告等办法传递消息,这样才能够管相关页面在新式状态,众所周知手动调用容易引入问题都非容易扩展。

以下是遵照系列文章的纲要:

手动传递状态的弊病还有代码的可读性降低,因为多仗会隐藏在Controller内部。另一个显而易见的是短是碰头带来代码的不一致性,因为每个工程师还起协调嗜的传递状态的艺术,当然这些题材得以透过代码规范还是代码评审流程来避免,但同时成本为不可避免的多,而经优质的框架可以为开发者自发统一作为,避免少走弯路,这为是框架的精所当吧。

ReSwift

ReSwift就是为着解决类似题材如果那个之,通过自律状态传递方式,这样可减掉开发者犯错的上空,且先后的易读性大幅增长。

Coordinator

除此以外ReSwift具有超过平台性,支持iOS, macOS 和 tvOS。

extension

ReSwift通过三良组件实现了数据流的唯有为流动。

VueLike

  • State: 保存应用所在状态, 且状态的改动只能在Store 中进行,
    当在状态变更时,Store会通知所有的观察者。
  • Action:不含有其他事情代码,Store会接受action并以该传递让Reducer,而Reducer会根据不同之action创建新的State。
  • Reducer:根据当前运state和目前action,并创立新的应用状态。

搭方式的嬗变

咱俩来通过一个加减法的计数器例子来探视Reswift如果工作的。
先是来定义应用的State, Action 和 Reducer:

在介绍 ReSwift 之前,我们先行来大概回顾下 iOS
端(不小心地说,也堪看作是运动端采用开发)的架演变史。

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

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

//Reducer
func counterReducer(action: Action, state: AppState?) -> AppState {
    var state = state ?? AppState()

    switch action {
    case _ as CounterActionIncrease:
        state.counter += 1
    case _ as CounterActionDecrease:
        state.counter -= 1
    default:
        break
    }

    return state
}

立马上头介绍的好章都相当的几近,重点要引进生 @Bohdan Orlov 的 iOS
Architecture Patterns,非常的体系跟容易掌握。

为保护State和受Action,我们尚欲定义Store, Store可具有全局属性。

Massive View Controller

let mainStore = Store<AppState>(
    reducer: counterReducer,
    state: nil
)

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    [...]
}

每当讨论架构模式的时候,MVC 是为提及最多的覆辙之一。众所周知,Apple 推出的
MVC 跟软件工程被传统的 MVC 是匪等同的。

终极就是于View层如何利用方面定义之老三零部件:

广大人于经的 MVC 中之 Model
一直留存误会,认为其代表的仅仅只是一个实体模型。其实,它纯粹的概念应该还含大量底政工逻辑处理,相对的
Controller 只是于 View 和 Model 层建立一个桥梁而已。

  • 挂号监听Store中State的别。
  • 触发Action事件,试图改变State。

流动:业界在迈入历程被,围绕 MVC 也延长讨论了广大之问题,典型的如果「胖
Model 和瘦 Model」 的题目,甚至于十几年前,曾经以 JavaEye 上特地针对
Model 的筹划来了同样次于相当热烈的座谈,帖子还以。

Apple 的 MVC 采用的是瘦 Model 的计划,ViewController
承载了大气之逻辑处理。之所以如此设计,也是发生由之。

class CounterViewController: UIViewController, StoreSubscriber {

   @IBOutlet var counterLabel: UILabel!

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

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

//如果状态发生变化,newState 方法会被自动调用。
   func newState(state: AppState) {
       counterLabel.text = "\(state.counter)"
   }

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

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

}

若以 iOS
平台跟浏览器进行对照,它们有大量可类比的一部分,但前者有只可怜特殊之地方,就是
iOS 和 Android
一样,都存在大明白的生命周期,这些生命周期的方式还有为
ViewController。

圆的代码样例可点击这里下载。

就此最初始的 iOS 架构问题不言而喻:超负荷臃肿的 View Controller
层大大降低了工的可维护性以及可测试性。

更多

引进阅读 《iOS
常见架构一探望》。

取更多内容要关注微信公众号豆志昂扬:

  • 一直长公众号豆志昂扬
  • 微信扫描下图二维码;

此地推荐生 @Krzysztof Zabłocki 的 Good iOS Application Architecture:
MVVM vs. MVC vs.
VIPER,他不只讲述了针对性两样架构的明亮,也提出了协调对好搭的鉴定标准。

MVP

缓解 Massive View Controller 的均等股良药来自于
MVP。这种规划思路的骨干是提出了一个 Presenter
层,它是连View层与Model层的桥梁并对准作业逻辑进行拍卖,这个可了俺们好好中之 单一职责规范。

MVVM

以笔者看来,MVVM 跟 MVP 其实是甚好像之,这种设计缓解了 Massive View
Controller 的题材,同时也引入了「双向数据绑定」,MVVM 也是 Web
前端同学好生熟识的定义。

可这样说,MVVM 应该是立 iOS 以及 Android 最盛的架构设计。

VIPER

VIPER 是 View + Interactor + Presenter + Entity + Router 的缩写。对比
Android,这种架构似乎在 iOS
界更盛,但是总体上而言,采用这种架构的统筹并无多。理论及,这是一律种植非常好的架思想,灵感于所谓的 The
Clean Architecture。

但是更仔细的模块化设计,也给 VIPER
被多丁熊为同样栽过度工程。对其感兴趣之同窗,可以看看 objc.io
的 Architecting iOS Apps with VIPER。

ReSwift

在水滴内部,我们既下过 Angular 1.x
开发工作,所以对于「双向数据绑定」的定义并无生。随着我们业务的消,我们连至了逾成熟的
Vue 2 + webpack 来组织 Web
前端的支出。在经验过不同之数码流方案之后,就偏爱而言,我们或更喜爱「单为数据流」的套路,缘自于子孙后代设计还简便,更便民测试。

所以,在念了 MVVM 这个成熟之解决方案后,笔者为开谋求 iOS
的光为数据流解决方案,后面发现了ReSwift,在经过简单周到之体验及测试,我们发现这恐怕是越切合组织审美偏好之等同栽架构设计。

Redux

如果了解「单为数据流」其实要上 Redux 就尽了。2014年 Facebook 提出了
Flux 架构的定义,2015年,Redux 出现,将 Flux
与函数式编程结合并,很紧缺日外虽改为了无以复加紧俏的 Web 前端架构。

基本设计

根据经典的 Redux 模型,ReSwift 也普及以下设计:

The Store:以纯数据结构管理全 app 的状态,状态只能通过
dispatching Actions 来拓展改动。一旦 store
中的状态改变了,它就是会见通报给有的 observers 。

Actions:通过陈述的样式来描述一不成状态变更,它不含有其他代码,存储于
store,被转正给 reducers。reducers 会接收这些 actions
然后进行对应的状态逻辑变更。

Reducers:基于当前的 action 和 app 状态,通过纯函数来回到一个初的
app 状态。

combineReducers

笔者发现在目前之 ReSwift 版本被,并没有供 Redux 中相应的
combineReducers 实现。猜想是实在与 Swift 与 JavaScript
之间的差异导致,与膝下即宗动态语言不通,前者有静态的档次。但这题材可以透过外措施来化解。

牛刀小试

今日咱们就算来探哪根据 ReSwift 创建一个 iOS 工程。

率先是项目结构设计,假要即是一个基本上职能的业务需要,看 ReSwift
是否可以组织一个针锋相对复杂的型。

色组织

AppDelegate.swift

importUIKit

importReSwift

let mainStore = Store(

reducer: appReducer,

state: nil

)

@UIApplicationMain

classAppDelegate: UIResponder, UIApplicationDelegate {

……

}

App/AppState.swift

importReSwift

struct AppState: StateType {

varmodule1State: Module1State

varmodule2State: Module2State

}

App/AppReducer.swift

importReSwift

importReSwiftRouter

func appReducer(action: Action, state: AppState?) -> AppState {

returnAppState(

module1State: module1Reducer(action: action, module1State: state?.module1State),

module2State: module2Reducer(action: action, module2State: state?.module2State)

)

}

Modules/Module1/State/Module1State.swift

importReSwift

struct Module1State {

……

}

Modules/Module1/Reducers/Module1Reducer.swift

importReSwift

func module1Reducer(action: Action, module1State: Module1State?) -> Module1State {

returndoSomething(module1State) ?? Module1State()

}

Modules/Module1/Actions/Module1Action.swift

importReSwift

struct Module1Action {

func action1(params: Int) -> Action {

returnAction1(params: params)

}

}

extension Module1Action {

struct Action1: Action {

let params: Int

}

}

即使如此,我们就了 Redux 相关的结构设计,至于 Redux 跟 ViewController
层如何整合,打交道。