关于swift:这种编码风格的mvvm模式是没有意义的?

mvvm pattern in this style of coding is meanless?

我已经用MVC模式开发了自己的项目,并试图转换为MVVM模式,但有时我认为它变得越来越糟糕和毫无意义。

这是我代码的一部分。我有如下控制器、模型和一个视图模型:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
struct FAQ: Mappable {        
    var id: String?
    var question: String?
    var answer: String?
    var datalist: [FAQ]?
    //var datalist: [Any]?

    mutating func mapping(map: Map) {
        id <- map["id"]
        question <- map["question"]
        answer <- map["answer"]
        datalist <- map["data"]
    }
}

class learningViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    @IBOutlet weak var faqLable: UILabel!
    @IBOutlet weak var learningLable: UILabel!
    @IBOutlet weak var uiviewHeader: UIView!
    @IBOutlet weak var barRight: UILabel!
    @IBOutlet weak var barLeft: UILabel!
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var backImage: UIImageView!

    var learningRequestSession: URLSessionDataTask?
    let address = Domains.address
    var objectData = faqViewModel()

    override func viewDidLoad() {
        super.viewDidLoad()
        objectData.faqFunc {
            self.setup()
        }
        setup()

    }

    override func viewWillAppear(_ animated: Bool) {
        tableView.reloadData()
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return objectData.objectData.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier:"faqCell", for: indexPath) as! customViewCellTableViewCell

        //cell.faqIcon.image = UIImage(named:"question")
        cell.faqTitle.text = objectData.objectData[indexPath.row].question
        cell.faqBody.text = objectData.objectData[indexPath.row].answer

        return cell            
    }
...
}

这是视图模型类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class faqViewModel {
    var objectData = [FAQ]()

    init(faq: [FAQ]) {
        self.objectData = faq
    }

    init() {}

    func faqFunc(complition: @escaping () -> () ) {        
        let url = URL(string:"\(address)faq/getdata")
        print(url!)

        URLSession.shared.dataTask(with: url!) { (data, response, err) in
            if let content = data {
                do {
                    let json = try! JSONSerialization.jsonObject(with: content, options: .mutableContainers) as Any

                    let mapper = Mapper<FAQ>().map(JSONObject: json)

                    self.objectData = (mapper?.datalist.map({ $0}))!
                } catch {
                    print(err)
                }
            }
        }.resume()
    }
}

faqfunc函数以前在MVC模式的控制器类中。

我已经移动它来查看这个模式中的模型。所以我觉得我做错了或者MVC更好…!


一些MVC问题在DaveDelongs的博客中有很好的描述。

我同意他,MVC在某些情况下可能会导致:

  • 大量的视图控制器(视图逻辑、业务逻辑和网络)通常被放置在*ViewController类中,这些类的增长有时非常大。

  • 不封装违规(例如,向segue中的ViewController传递数据等)

  • 可测试性。MVC通常需要编写集成测试,这些测试很难维护,并且需要非常好的UIKit知识。

  • MVVM

    值得一提的是,MVVM基本上是一个花哨的MVC。

    MVVM试图解决MVC模式的一些缺陷。它改善了关注点的分离,使逻辑更加清晰。不再有大量的视图控制器(正确使用)。imho,MVVM的最大好处是可测试性。现在我们有了ViewModel,对象包含所有与视图相关的数据。所以编写测试不再需要集成测试。但是使用MVVM通常连接到某种反应式编程。这本身就隐藏着陷阱和陡峭的学习曲线。

    MVVM PROS

  • 更好的可测试性
  • 更好地分离关注点
  • 摆脱大规模的视图控制器
  • 它有点符合Cocoatouch MVC范式
  • 我想还有更多

    MVVM CONS

  • 使用反应式框架需要"思维定势"的改变,因此-陡峭的学习曲线
  • 很容易使模型和视图不同步
  • 观察逻辑容易出错
  • 更多

    结论

    MVVM是一个很好的工具,如果使用得当,它可以修复一些MVC缺陷并提供生产效益。MVVM需要一些努力和最佳实践学习。但是,在深入研究它之前,我建议阅读Dave Delong的博客系列"一个更好的MVC",并记住,MVC是一个本地的苹果模式,通过实现它,您可以在更新SDK时"安全"地避免大的意外。

    另外,我非常喜欢正确使用MVVM,但不正确的使用有时会让我感到害怕。


    视图模型是一种用于视图中的迷你模型。因此,您将视图属性绑定到它,并管理每个属性中的更改:

    视图已更改->查看模型更新

    视图模型已更改->查看更新

    您编写的faqViewModel类是一种apiRequestLoader,不属于视图模型。有关更多信息,我建议您对Clean Swift ArchitectureSwift Viper Architecture进行一些研究,如果您想了解更多关于如何将网络请求与应用程序其他部分分离的信息,可以观看WWDC 2018会议。