談談我現在使用的設計模式

我要在河邊釣一整天的魚發表於2017-12-19

1、傳統的MVC

1.png
可以看出另外每個實體都知道另外兩個實體,這顯然降低了可重用性當然也不是您在開發中想要的。

2、蘋果的MVC

2.png
這裡View和Model的關係剪斷,但是在Controller中會變得很臃腫,Controller中程式碼量會變得很大。想想將業務邏輯、網路請求、View狀態改變還有把addSubView的程式碼也放在Controller中的,看了眼要修改的Controller是不是想死的心都有了。

3、我的MVC

設計模式不是死,根據自己的需求和理解進行一些改變是必要的,再變也是萬變不離其宗,現在的專案的使用的MVC實際上就是對Controller的瘦身。上圖是取自iOS Architecture Patterns,這裡我直接說我的實現。

我的目錄是根據模組進行分解然後在模組目錄下建立MVC的資料夾,我不喜歡大的MVC檔案目錄然後吧相關的類放進對應的資料夾下的。

3.png

Model

和你所知MVC中的M是一樣的

/
//  Model.swift
//  Test
//
//  Created by 小七 on 2017/9/19.
//  Copyright © 2017年 Seven. All rights reserved.
//

import UIKit

struct Model {
    var name: String?
}
複製程式碼

View

我不會在Controller中寫addSunViews這樣的程式碼, 所以這樣的程式碼全在封裝帶View中了,這裡用的Storyboard。我將storyboard放在Controller中純屬個人習慣,我個人認為這個是屬於View的

//
//  TableViewCell.swift
//  Test
//
//  Created by 小七 on 2017/9/19.
//  Copyright © 2017年 Seven. All rights reserved.
//

import UIKit

class MyTableViewCell: UITableViewCell {

    @IBOutlet weak var label: UILabel!
    
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

}
複製程式碼

Controller

Controller中含有Request和C->V的數值傳遞類, 在實際專案中將一部分的業務邏輯程式碼放在了ViewModel中了(這裡的ViewModel並不是MVVM中所表達的意思,只是借鑑了一些思路)

//
//  ViewController.swift
//  Test
//
//  Created by 小七 on 2017/9/19.
//  Copyright © 2017年 Seven. All rights reserved.
//

import UIKit

class ViewController: UITableViewController {

    lazy private var mViewModel: ViewModel = ViewModel()
    lazy private var mRequest: Request = Request()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        mRequest.request {[weak self] in
            self?.tableView.reloadData()
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        
    }
    
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return mRequest.list.count
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "MyTableViewCell", for: indexPath) as! MyTableViewCell
        mViewModel.loadCellWithModel(mRequest.list[indexPath.row], view: cell)
        return cell
    }
}
複製程式碼

ViewModel

這裡做了資料的傳遞

//
//  ViewModel.swift
//  Test
//
//  Created by 小七 on 2017/9/19.
//  Copyright © 2017年 Seven. All rights reserved.
//

import UIKit

class ViewModel: NSObject {
    
    func loadCellWithModel(_ model: Model, view: MyTableViewCell) {
        view.label.text = model.name
    }
    
}
複製程式碼

Request

網路請求的封裝和Model的儲存,我的Controller中是不儲存Model的

//
//  Request.swift
//  Test
//
//  Created by 小七 on 2017/9/19.
//  Copyright © 2017年 Seven. All rights reserved.
//

import UIKit

class Request: NSObject {
    
    var list: [Model] = [Model]()
    
    func request(result: () -> Void){
        for _ in  0 ... 20 {
            var m = Model()
            m.name = "12345"
            list.append(m)
        }
        result()
    }
    
}
複製程式碼

後語

實際上MVVM和MVP可以也可以解決C過於臃腫的問題。那為什麼沒有使用流行的MVVM呢,因為MVVM的實現離不開RX和RAC,主要專案中沒有使用它們所以就沒有直接引入MVVM(這個理由確實牽強 = =!),還有建議使用的所有第三方庫最好自己進行封裝下,不然在換庫的時候會留下悔恨的淚水。

git地址go go

謝謝觀賞,這裡是我在專案中對MVC的理解,希望多多指正

參考

iOS Architecture Patterns

相關文章