在iOS中,每个UIView都应该有一个UIViewController吗?

时间:2015-10-18 03:30:21

标签: ios uiview uiviewcontroller

许多视图的子视图不一定需要将自己的控制器与它们相关联。在Apple的own tutorial中创建自定义视图时,它们实际上并不为每个子视图创建一个子UIViewController。

但是,我经常遇到这样的情况:我将拥有一个视图层次结构,其中子视图的某个子视图有一个发送网络请求的按钮。在那种情况下,我可以做一个目标:

myView.addTarget(self, action: "networkRequest:", forControlEvents: UIControlEvents.TouchDown)

然后在同一个myView类中我可以处理该网络请求,但这似乎打破了MVC模式。 View不应该做逻辑,他们应该只显示东西,对吗?

我们可以做的另一个选择让每个视图都可以访问逻辑所需的父控制器或祖父控制器。在我的目标可能看起来像这样的情况下:

func networkRequest(view : MyView) {
    self.controller.doNetworkRequest()
}

但这似乎也不是一个正确的解决方案。再一次,似乎我们只是打破了MVC并且贬低了。

相反,就我所见,我们只剩下两种选择之一:

首先,我们可以从父控制器本身添加目标和所有逻辑。但这样做会给我们带来令人讨厌的链条:

self.grandParentView.parentView.childView.addTarget(self, action: "networkRequest:", forControlEvents: UIControlEvents.TouchDown)

那长长的访问列表让我感到寒意,看起来很糟糕。但是,它似乎仍然遵循MVC。从技术上讲,我们在控制器中执行逻辑,对吧?

但可能还有其他选择。我们可以给每个视图一个控制器,让每个UIViewController都有一个子控制器用于每个新的子视图。

但是,有些观点是静态的。它们实际上没有任何逻辑,因此它们不一定需要控制器。但是,如果我们要遵循这个约定,我们基本上需要每个视图一个,否则我们会有一个不一致的地方,控制器有一个孙子控制器,但没有子控制器。

因此,我们只为我们的控制器创建了许多空的棺材。这会构建许多永远不会被使用的死代码,这会导致一些软件腐烂。

那些比我更聪明,更聪明的人,这里有什么正确的解决方案?

3 个答案:

答案 0 :(得分:4)

有可能MVC大师比我更聪明,但我会给它一个解决方案:

选项1 - 失败

如果您正在处理UIView子类中的网络请求,那么您肯定会破坏MVC模式。根据Apple的MVC参考:

  

视图对象是用户可以看到的应用程序中的对象。视图对象知道如何绘制自己并且可以响应用户操作。

看起来,视图应该只是处理用户可以看到和与之交互的内容。 走这条路。

选项2 - 成功

让我们回到Apple对视图控制器的MVC参考:

  

控制器对象充当应用程序的一个或多个视图对象与其一个或多个模型对象之间的中介。因此,控制器对象是视图对象通过其获知模型对象的变化的管道,反之亦然。控制器对象还可以为应用程序执行设置和协调任务,并管理其他对象的生命周期。

请注意该文档如何表示"一个或多个,"因为在视图控制器中处理多个视图的后勤是完全可以接受的。就个人而言,我要说的是,如果您的视图只有一个需要代表网络请求的按钮,请继续将父视图的视图控制器设置为代理。

一旦视图的数据处理变得复杂,就应该让视图拥有自己的视图控制器,"为了简明起见,我将其定义为"多个动作,这些动作将掩盖父视图的视图控制器的明显目的。"

话虽这么说,可以在视图控制器中清楚地标记#pragma mark确切地说代码就在哪里,所以在这里使用你的判断。

选项3 - Ehhh ......

为每个视图提供自己的视图控制器绝对可行,但你真的认为这是必要的吗?如果应用程序具有扩展性,那么每次需要处理单个按钮时创建一个全新的视图控制器当然看起来有点过分。

总结

使用选项#2并使用您的最佳判断。打破MVC模式你不会受到惩罚。最糟糕的是,如果您的视图逻辑变得复杂,您将把代码重构为新的视图控制器。

更多参考:

Model-View-Controller - iOS Developer Library

希望这有帮助!

答案 1 :(得分:3)

首先,非常好地提出问题!

回答你的问题 - 不是每个UIView都没有必要让一个视图控制器来管理它们,但是行业明智的做法是自行卸载UIView管理 - MVC设计模式

我建议使用代表。它可以很好地保持MVC模式的完整性并使自定义UIView可重用。

我有很多自定义UIViews,我在多个视图控制器中使用它们。我处理它们的方式是:

  1. 创建协议并在其中添加必要的方法。
  2. 视图控制器是否符合该协议。
  3. 实施必要的协议方法。
  4. 处理UIView中的UI动作触发器,并将处理传递给代表谁。

答案 2 :(得分:0)

让我们从基础开始...视图应该是愚蠢的。

如果您编写的视图具有应用程序逻辑,业务逻辑或引用模型对象,那么您做错了。

注意:这包括表格视图单元格和集合视图单元格!!

您对此问题有正确的答案。

  

首先,我们可以从父控制器本身添加目标和所有逻辑。

但是,你有一个问题。

  

但这样做会给我们带来讨厌的链条

实际上,这应该是一个非问题。保持自定义视图平整。您应始终能够保持最多1级视图间接(视图属性是间接的第二级)。

myView.mySubview
myView.mySubview.myProperty

为了实现这一目标,我尝试遵循一些基本规则。

  1. 保持观点简单。
  2. 支持继承优于撰写以添加新功能。
  3. 当其他所有方法都失败时,请使用容器视图(这是您应该如何看待子视图控制器)。