美文网首页SwiftiOS开发那些事Swift学习
基于Swift的MVVM的一套简单实现

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

作者: 王渊鸥 | 来源:发表于2018-04-03 21:51 被阅读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的存在, 将逻辑变得更加清晰明确, 而这恰恰就是我们的产品意义. 

    完整的代码如下:

    相关文章

      网友评论

        本文标题:基于Swift的MVVM的一套简单实现

        本文链接:https://www.haomeiwen.com/subject/sgachftx.html