【问题标题】:Best approach for composing UIViews to create complex views? [closed]组合 UIView 以创建复杂视图的最佳方法? [关闭]
【发布时间】:2017-03-18 22:05:22
【问题描述】:

从 web-stack 过渡到 iOS 仙境,我发现很难理解如何重新构建我对 MVC 的想法并在 iOS 上有效地构建我的 UI .

前提:

  • 在网络堆栈中:
    • Controller一般对应一个URL,view代表页面。
    • 视图可以通过 CSS +Javascript + 片段实现不重复代码。
  • 在 iOS 中:
    • 在对应于 UIViewController 的新屏幕上。
    • 我们有一个 UIView 组成自己的 UIViews
    • UIViews 与 UIViews 一起存在,UIViewController 与 UIViews 存在,UIViewController 与内联 UIViews 存在
    • 我们绝对将繁重的或数据逻辑委托给最近的控制器
    • 在 iOS 中感觉主要是 先查看,这很棒

问题:

将视图组合到我的self.view 的最佳方式是:

  • UIView 类的视图
  • UIViewController 出现的视图具有关联的UIView 类。
  • UIViewController 出现的视图,内联UIView

示例视图层次结构:

------------------------------
|             A              |
|                            |
|    --------------------    |
|    |        B         |    |
|    |                  |    |
|    |  --------------  |    |
|    |  |     C      |  |    |
|    |  |            |  |    |
|    |  |            |  |    |
|    |  |            |  |    |
|    |  |            |  |    |
|    |  |            |  |    |
|    |  |            |  |    |
|    |  --------------  |    |
|    |                  |    |
|    --------------------    |
|                            |
------------------------------

[具体细节]我的~不舒服~经历:

  • A 可能 [self addView:B_view](如果 B 只是 UIView)
  • A 也可能是 [self addView:B_viewController.view](如果 B 有视图控制器)
  • A 也可能是 [B setChildView:C_view]
  • 我们可以有B_viewController.delegate = A & C_viewController.delegate = A
  • 我们可以有B_viewController.delegate = A & C_view.delegate = B
  • 在所有这些情况并存之后,我们必须考虑界限
  • 我看到 A 通过长委托链回答了 C 的问题。

逻辑分散在委托、视图控制器和视图中

分离关注点 - 但如何?

除了可以改善上述体验的论点“抽象好和关注点分离”。我认为 viewController 和 viewController.view 的出血很容易导致广泛的耦合。

这很快变得令人困惑,感觉就像意大利面,尽管努力也难以控制。

也就是说,

  • 解决上述缺陷的最佳做法是什么?
  • 什么是绝对不能做的?
  • 当很难提出好的论据时,我们如何避免长的委托链,因为当委托有效地表示您可以更好地处理这个问题时?

【问题讨论】:

  • 问题来自实践经验,我相信不只是我,应该作为一个很好的资源。
  • 很好的问题,不明白反对意见。虽然不确定我能回答,但我经常问自己同样的问题。
  • 好问题。 OP已经完成了他的作业并很好地组织了这个问题。请添加拒绝投票的理由。
  • 如果这被标记为“太宽泛”,在 Stack 网站的什么地方可以问这样的问题?
  • 既然你问的是应用架构相关的问题,我建议你阅读以下关于iOS应用架构的文章medium.com/ios-os-x-development/…

标签: ios cocoa-touch uiview uiviewcontroller


【解决方案1】:

作为一个做过大量 iOS 编程并且现在花费大量时间在 Angular 开发上的人,这里有一些快速的想法:

UIView 代表基本屏幕构建块;也就是说,它损害了视图、一些数据以及在视图上呈现该数据的逻辑。因此它可以用来绘制一些文本或图形,或者它可以包含任意数量的具有相同能力的子视图。在 Angular 世界中,UIView 将(在某种程度上)等同于封装 HTMLCSSJavaScript 等的 Component,但也可以包含其他组件。

如您所知,iOS 提供了许多预构建的原生 UIView - UILabelUIButtonUITable 等,这些都适合大部分应用程序需求。

UIViewControllerUIView 具有更多的结构功能。它与导航框架集成,以便开发人员可以快速为用户更改上下文。它包含一个“主”UIView,它作为上下文的基础平台,包含任意数量的本机和自定义UIView's。它的目的是帮助配置那些UIViews给定当前应用上下文

如果UIViewController 正在以不限于当前应用上下文的方式配置UIView,那么UIView 可能应该扩展为自定义对象。这样它就可以自我管理并且更容易在其他环境中重用。

另一件事:

代理在适当的时候很棒,但NSNotification 是一种简单而强大的方式来观察变化,同时避免对象依赖的意大利面条。

【讨论】:

    【解决方案2】:
    • 你可以有一个 ViewController

    • 将 UIView 分离到 ViewController。它不应该与 viewController 紧密耦合。

    • 让您的 View 在 UIView 类本身中登录。创建自己的委托和协议。并在任何视图控制器中使用它。

    • 将视图控制器添加到视图控制器不是一个好的解决方案。

    • 您还可以迁移到 MVVM,每个视图在其视图模型中都有其逻辑部分,但一开始可能会令人困惑。

    • 尝试将 UIViews 分离到 ViewControllers。

    【讨论】:

      【解决方案3】:

      也许,您正在处理的是 MVC - Massive View Controllers 困境。这是一篇有趣的读物,其中 Marcus 谈到通过将代码放在其所属的位置、网络层、持久层或表示层(理想情况下是视图控制器)来有效地管理代码。

      http://www.cimgf.com/2015/09/21/massive-view-controllers/

      除了委托模式,我们还有基于块/闭包的方法,这可能有助于清理代码。

      https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithBlocks/WorkingwithBlocks.html

      总的来说,Robert C. Martin 的简洁代码方法在这里可能会有所帮助。通过称为 VIPER 架构的方式来实现它。这是一个教程。

      https://www.objc.io/issues/13-architecture/viper/

      Objective C,作为一种语言包含委托模式,并且将它用于大多数人的关注点是一种标准做法。

      欢迎来到 iOS 平台。

      【讨论】:

        【解决方案4】:

        我未能在 stackoverflow 上提出类似的广泛问题 - 似乎社区更喜欢更具体的技术问题。但我会试一试。请记住,以下所有内容都是我的意见,而不是硬性规定。

        我觉得这是一个关于消息传递和设计模式的综合问题。在组件通信方面(无论是视图还是控制器),有很多方法可以解决,每种方法都有+-(或者更确切地说是用例)。有:委托、响应者链、块、通知、反应信号 - 仅举几例。

        TL;DR

        • 我个人的偏好绝对是让视图尽可能简单,并将业务逻辑放在其他地方(取决于您选择的模式),以便更好地组合。
        • 您的直觉与我的一致:每当您的组件(视图或视图控制器)在执行 self.superviewself.parentViewController(甚至有人说是 self.navigationController)时,它可能违反封装并且有更好的方法。
        • 长委托链绝对是个问题。有时它们很容易理解,有时则不然,但这并不是世界上最糟糕的事情,尽管可能有更好的方式来处理沟通。

        以下是一些随机观察,可能会将您带到某个地方(或可能不会)。

        MVC 是一种在 iOS 中获取用户的快速(且肮脏)方式

        在我看来,MVC 是一个非常适合小型项目的模式(从“简单 vs 简单”来看很容易)。但是从个人经验来看,当您正在处理的屏幕的复杂性增加时,它很快就会失控。趋势是让控制器处理从用户交互到网络的所有事情,它很快就变成了一个 1k 长的怪物。

        遗憾的是,iOS 架构中的很多东西都依赖于UIViewController。通常,它不可避免地成为您的代码与操作系统的第一个接触点,但它不必在内部处理所有事情。相反,它可以将职责路由到适当的组件,即

        func loginButtonDidTap(_ sender: UIButton) {
          loginManager.beginLogin(from: self)
          analytics.reportLogin(with: sender)
          // ...
        }
        

        编写控制器也可以

        我并没有从您的描述中完全注意到,但是如果您更喜欢使用 MVC,那么它是编写控制器的完全有效的选择。这是为 iPad 构建时非常常见的情况,但即使在 iPhone 上,每个屏幕都可以轻松包含完全独立的部分,其中每个部分都是单独的 ViewController,那么您应该查看所谓的“UIViewController 包含”。大多数情况下,它允许更好的分离和重用,但同样不能解决主要问题。

        一定要探索其他模式

        如果你正在阅读这篇文章,你非常渴望学习?在这种情况下,我建议不要停止使用 MVC。有许多有趣的设计模式可能适合也可能不适合您的特定需求。 MVVM (现在?)非常流行。最近单向流似乎是新的热门事物。灵感来自 JS 的 Redux。这与 MVC 大相径庭,如果您有兴趣,我建议您查看这个项目 https://github.com/ReSwift/ReSwift

        遗憾的是,就像任何架构问题一样,没有对错之分——只有对你和你的团队有用的东西。而且我很想在问题以“太宽泛”而结束之前听到其他观点?

        很抱歉,如果这完全不是您所要求的,请告诉我您是否想讨论任何特定方面。

        【讨论】:

          猜你喜欢
          • 2012-01-15
          • 1970-01-01
          • 2013-03-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多