MVVM在swift中的应用

概念
讲述MVVM的文章很多,我就不多描述了,本篇主要讲的是在swift项目中的应用
模块
MVVM模块中,view、controller、model、viewModel,其中view和controller可以看成同类的,也可以不同类的
交互关系
view -> controller、viewModel
model -> viewModel
viewModel -> model、controller、view
controller -> view、viewModel
其中,

  • model
    仅仅作为数据模型的形式存在(从网络端等获取的数据模型),不进行数据的加工(如时间戳转为字符串时间、一些字符串的加工等)
  • viewModel
    1、获取数据model(网络请求等方式获取)
    2、对model进行数据加工,并转为viewModel属性,用于数据展示
  • view
    1、和viewModel交互:将viewModel中的数据展示
    2、和controller交互:用于UI渲染
    不和model交互
  • controller
    1、和view交互
    2、和viewModel交互(获取数据等)
    3、不与model相关联

案例
此案例为一个从网络获取新闻数据列表,渲染的过程
第一步,在viewModel(WCNewsLoaderViewModel)中获取网络数据,并将网络数据转为用于展示的viewModel(WCNewsListViewModel),需要展示的内容包含图片、标题、内容、时间数据
WCNewsModel
数据模型-仅仅作为一个模型来接收数据(网络请求等方式获取的数据)

class WCNewsModel: NSObject {
   var iconName:String?
   var title:String?
   var content:String?
   var time:String?
}

WCNewsLoaderViewModel
网络请求的viewModel-进行网络请求的过程,并且将请求到的数据转为可以直接使用的另外一个viewModel

class WCNewsLoaderViewModel: NSObject {
    var listViewModels:[WCNewsListViewModel] = []
    
    //获取数据
    public func getData(_ closure:@escaping()->()) {
        //模拟网络请求延时获取数据
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            let array = ["pic_area_balcony", "pic_area_bedroom", "pic_area_corridor", "pic_area_kitchen", "pic_area_livingroom", "pic_area_study", "pic_area_toilet", "pic_area_toilet", "pic_area_toilet"]
            for (index, item) in array.enumerated() {
                let model = WCNewsModel()
                model.iconName = item
                model.title = "这里是标题\(index)"
                if index == 1 {
                    model.title = "今天晴"
                }
                model.content = "内容"
                if index == 2 {
                    model.content = "这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容这里是内容"
                }
                model.time = "2022-09-15 15:57:\(index)"
                
                let listViewModel = WCNewsListViewModel(model: model)
                self.listViewModels.append(listViewModel)
            }
            closure()
        }
    }
}

WCNewsListViewModel
数据的viewModel-已经处理好数据的viewModel,可直接用于数据的展示

class WCNewsListViewModel: NSObject {
    var iconImage:UIImage?
    var title:String?
    var content:String?
    var time:String?
    
    var model:WCNewsModel
    
    init(model:WCNewsModel) {
        self.model = model
        super.init()
        
        self.handleModel()
    }
    
    private func handleModel() {
        if let iconName = self.model.iconName {
            self.iconImage = UIImage(named: iconName)
        } else {
            self.iconImage = nil
        }
        self.title = "标题:" + (self.model.title ?? "")
        self.content = "正文:" + (self.model.content ?? "")
        self.time = "时间:" + (self.model.time ?? "")
    }
}

WCNewsViewController
控制器-用于绘制UI、协调交互等

class WCNewsViewController: UIViewController {
    
    private lazy var newsLoaderViewModel:WCNewsLoaderViewModel = WCNewsLoaderViewModel()
    
    private lazy var tableView:UITableView = {
        let tableView = UITableView.init(frame: self.view.bounds)
        tableView.backgroundColor = .white
        tableView.separatorStyle = .none
        tableView.delegate = self
        tableView.dataSource = self
        return tableView
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.backgroundColor = .gray
        self.view.addSubview(self.tableView)
    
        self.getData()
    }
    
    deinit {
        print("deinit ===" + NSStringFromClass(self.classForCoder))
    }
}

extension WCNewsViewController {
    private func getData() {
        self.newsLoaderViewModel.getData {
            self.tableView.reloadData()
        }
    }
}

extension WCNewsViewController:UITableViewDelegate, UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.newsLoaderViewModel.listViewModels.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = WCNewsTableViewCell.wc_baseTableViewCell(tableView: tableView) as! WCNewsTableViewCell
        
        let listViewModel = self.newsLoaderViewModel.listViewModels[indexPath.row]
        cell.listViewModel = listViewModel
        
        return cell
    }
}

总结
1、controller用于绘制UI、协调各种行为等
2、view用于绘制UI
3、model用于数据模型存储
4、viewModel用于网络请求、数据处理等

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容