如何在Swift中尊重MVC?

如何在Swift中尊重MVC?,swift,design-patterns,model-view-controller,Swift,Design Patterns,Model View Controller,我想知道您是如何在使用Swift的IOS开发中正确地尊重MVC设计模式的?我现在的感觉是,视图控制器将控制器部分和视图部分混合在一起,但感觉不对?为了尊重MVC,我们显然需要将控制器和视图分开你是怎么做到的? 也许,对于其他设计模式,如MVVM或MVP,这一点更为明显。您可以将项目分开,并创建一个结构,其中所有逻辑和模型都放在一个位置,所有视图控制器都放在一个位置 例如: Core Models Person.swift Car.swift Hel

我想知道您是如何在使用Swift的IOS开发中正确地尊重MVC设计模式的?我现在的感觉是,视图控制器将控制器部分和视图部分混合在一起,但感觉不对?为了尊重MVC,我们显然需要将控制器和视图分开你是怎么做到的?
也许,对于其他设计模式,如MVVM或MVP,这一点更为明显。

您可以将项目分开,并创建一个结构,其中所有逻辑和模型都放在一个位置,所有视图控制器都放在一个位置

例如:

Core
    Models
        Person.swift
        Car.swift
    Helpers
        Extensions.swift
        APIHelper.swift
    Webservice
        Webservice.swift


Controllers
    ViewController.swift
    SecondViewController.swift

因此,您基本上拥有
核心中的所有逻辑和计算,以及
控制器中的所有视图和UI元素。通过这种方式,您不必多次执行相同的逻辑代码。您还可以创建自定义视图,并将它们添加到
核心中,稍后可以在
控制器中调用该核心

将常用的
视图控制器
分为两部分:
视图
演示者
<代码>查看
仅用于显示数据和收集用户交互的响应<代码>演示者
准备用于查看的数据,并处理来自
视图的用户操作

这个想法来源于鲍勃叔叔,并在建筑中得以实现

视图
有两个协议:

  • ViewInput
    :包含传递数据显示的函数,如
    set(labelText:String)
    。此协议应实现
    视图
    Presenter
    具有类型为
    ViewInput
    的对象
  • ViewOutput
    :包含函数,当视图中发生某些事件时,如
    viewDidLoad()
    rowDidSelect(at:indepath)
    时调用这些函数。此协议应实现演示者
<代码>视图
具有类型为<代码>视图输出的对象 毒蛇不是一件小事,我花了几天时间来理解它的原理。因此,请阅读文章并尝试在代码中实现它。不要犹豫提问。

尽管回答这样一个问题可能过于宽泛,但我将回答您关于以下方面的具体问题:

视图控制器混合控制器部分和视图部分


请注意,在处理iOS项目时,它会隐式地引导您应用该模式。默认情况下,视图控制器表示
控制器
部分,.storyboard和.xib文件表示
视图
部分,用于封装数据的任何模型对象(数据模板)表示
模型

我现在的感觉是视图控制器混合了 控制器部分和视图部分,但感觉不对,对吗

视图控制器有许多需要处理的职责,除了解释用户操作之外,它还应该是视图和模型之间的中介,并且不要忘记处理与web服务的集成。。。这就是海量视图控制器的问题

如果你试图做一些关于解决这个问题的研究,你会发现很多方法可以遵循,比如应用其他结构模式,比如MVVM、MVP、VIPER或Clean Architecture,或者更简单的方法,比如划分项目文件,以增加作业的独立性,从而使其更清晰、更易于跟踪,MVC-N可能是一个很好的例子

但对于您要询问的具体情况(混合控制器部分和视图部分),以保持简单:我建议根据其视图分离数据表示的逻辑,例如:

构建IOS项目时最流行的一种情况是使用TabVIEW及其单元格,请考虑以下内容:

ViewController.swift:

class ViewController: UIViewController {
    // ...
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return myDataSourceArray.count
    }

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

        // ...

        return cell
    }
}
class MyCustomCell: UITableViewCell {
    @IBOutlet weak var lblMessage: UILabel!
}
MyCustomCell.swift:

class ViewController: UIViewController {
    // ...
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return myDataSourceArray.count
    }

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

        // ...

        return cell
    }
}
class MyCustomCell: UITableViewCell {
    @IBOutlet weak var lblMessage: UILabel!
}
现在,想象一下——不知何故——在这种情况下,需要基于一系列复杂的计算来更改单元格中的
lblMessage
标签文本颜色:

不要这样做:

这会导致视图控制器变得庞大并包含大量作业,请执行以下操作:

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

    //...

    cell.doCalaulations()

    return cell
}
在单元类中:

class MyCustomCell: UITableViewCell {
    @IBOutlet weak var lblMessage: UILabel!

    func doCalaulations() {
        // do calulations which might needs tens of lines to be achieved, based on that:
        blMessage.textColor = UIColor.red
    }
}

这使得项目组件更加封装,重要的是视图控制器不必处理整个事情。对我来说,在与此类似的情况下,我甚至更愿意将
blMessage
设置为
private
,这保证了它只能从owner类(更多封装)编辑来处理任何需要的行为,因此,任何视图控制器都应该调用类方法,而不是直接访问其属性和iboutlet。

创建自定义视图?斯坦福斯威夫特课程非常漂亮地解释了如何在iOS应用程序中实现。为什么用过去式写作?“您是如何在使用Swift的IOS开发中正确遵守MVC设计模式的?”何时?“你是怎么做到的?”什么时候?对不起,英语错了我不明白“这个协议应该实现演示者”。意思是演示者需要实现ViewOutput协议,对吗?是的,它是。例如,演示者应该在显示视图之前设置UI。因此,在
视图中
viewDidLoad()
将调用
presenter.didLoad()
。在
presenter.didLoad中,
将被调用
set(label1Text:“first”)
好的,如果我觉得它更干净,我必须在我的进一步开发中尝试尊重它。视图是一个视图控制器,对吗?你可以阅读rambler的VIPER书。这本书有很多问题的答案,这些问题可能会出现。问题是“如何尊重MVC”,你为什么要谈论VIPER?请注意,这是传统MVC的更新版本,这被称为MVC-N。因此,您建议将某个类拥有的任何outlet设置为私有,以确保(并强制)调用该类方法和