SwiftiOS开发那些事Swift学习

基于Swift的MVVM的一套简单实现

2018-04-03  本文已影响2088人  王渊鸥

有人曾经问我基于Swift的MVVM的实现, 我当时给出的回答就是自己到网上去搜索Swift+MVVM. 我不知道这位哥们是否解决了问题, 但是, 最近我自己在搜索Swift+MVVM的时候, 发现大部分文章都非常有限, 一是不够MVVM, 大部分在玩各种概念, 而事实上, 不管MVC, MVP或者MVVM, 单纯的描述概念没有意义的, 直接一段代码就能非常深刻的理解MVVM的核心逻辑; 二是不够Swift, 要嘛拿KVC来说事, 用Swift实现一套Objective-C的代码, 要嘛直接拿RxSwift来说事, 把原本简单的MVVM逻辑越讲越复杂. 

我自己新建了一个项目, 写了一些代码, 试图用最简单的逻辑来解释清楚MVVM是什么. 

不管哪种模式, 真正纯正的MVVM是不存在的, 作为开发人员, 真正目的是实现功能的产品化, 而不是完成一个学院派的纯正的模型实现. 我们真正需要搞清的, 就是View和ViewModel之间的关系即可, 至于Model部分的缺失或者iOS开发中天然存在的Controller部分, 就当是一个额外的部分. 

另外一点, 我们不要放弃Storyboard, 这是最简单实用的工具, 有好用的工具, 就不要回归到最原始的代码写界面. 

StoryBoard添加两个控件

我们来假设一个最简单的需求, 就是点击按钮之后, Label和Button的标题都更改掉. 那么, 我们拉好两个控件:

class ViewController: UIViewController {    

    @IBOutlet private weak var testLabel: UILabel!    

    @IBOutlet private weak var testButton: UIButton!

...

拉好的控件是没有private的, 加上private是为了防止外部不通过VM强制修改控件. 

然后我们再建立一个ViewModel, 对应上这两个控件

class TestViewModel {    

    private weak var testLabel:UILabel!    

    private weak var testButton:UIButton!     

}

再添加init函数, 将ViewModel的控件和ViewController的控件关联起来. 

class TestViewModel {    

    private weak var testLabel:UILabel!    

    private weak var testButton:UIButton!    

    init(l:UILabel, b:UIButton) {        

        testLabel = l        

        testButton = b    

    }

}

其实有更好的办法获取到ViewController中的控件, 并且绑定起来, 不过, 通过init函数是最简单的办法. 

之后, 我们在viewDidLoad函数中将ViewModel实例化

class ViewController: UIViewController {    

    @IBOutlet private weak var testLabel: UILabel!    

    @IBOutlet private weak var testButton: UIButton!         

    var vm:TestViewModel!         

    override func viewDidLoad() {        

        super.viewDidLoad()        

        vm = TestViewModel(l: testLabel, b: testButton)    

    }

}

好了, 这样, 一个简单的ViewModel就对应上实际的View内容了. 之后我们将可以具体数据和控件的变化关联起来. 在这一部分, 大部分网络上文章的做法是使用KVO, 但那其实是一种非常高成本的做法, 代码复杂度平白增加了很多. 我们其实完全可以使用Swift的get/set来实现. 

在TestViewModel中添加如下两个函数

var testText:String?{

        get { return testLabel.text }

        set { testLabel.text = newValue }

}

var submitText:String? {

        get { return testButton.title(for: .normal) }

        set { testButton.setTitle(newValue, for: .normal) }    

}

最后, 我们设定一个点击事件, 通过修改viewModel的实例, 即可快速更改内容

@IBAction func onClick(_ sender: UIButton) {

        vm.testText = "aaaa"

        vm.submitText = "bbbbb"    

}

好了. 这就实现了一个最最基本的MVVM了(事实上, 这是一个VVM), 不过, 这已经够了. 它真正解决的问题, 并不是实现一套多余ViewModel出来, 而是在代码量大到一定程度的时候, 反而会因为ViewModel的存在, 将逻辑变得更加清晰明确, 而这恰恰就是我们的产品意义. 

完整的代码如下:

上一篇下一篇

猜你喜欢

热点阅读