2013-05-13 39 views
22

比方说,我们有以下类别:视图应该保存模型引用吗?

查看

@interface ArticleView : UIView 
@property IBOutlet UILabel *titleLabel; 
@property IBOutlet UILabel *bodyLabel; 
@end 

型号

@interface Article : NSObject 
@property NSString *title; 
@property NSString *body; 
@end 

控制器

@interface ArticleViewController : UIViewController 
@property Article *myArticle; 
@property ArticleView *myArticleView; 
- (void)displayArticle; 
@end 

@implementation 
- (void)displayArticle { 
    // OPTION 1 
    myArticleView.titleLabel.text = myArticle.title; 
    myArticleView.bodyLabel.text = myArticle.body;  

    // ... or ... 

    // OPTION 2 
    myArticleView.article = myArticle; 
} 
@end 

OPTION 1

  • PRO:两者视图和模型不连接到彼此。
  • CON:控制器需要知道,这两个模型和视图的细节。

OPTION 2

  • PRO:控制器代码轻且柔性的(如果视图或模型改变,则控制器代码保持相同
  • CON:的视图和模型是耦合的,因此可重用性较差

在选项2中,A rticleView将不得不改变,以保持对模型的引用:

@interface ArticleView : UIView 
@property IBOutlet UILabel *titleLabel; 
@property IBOutlet UILabel *bodyLabel; 
@property Article *article; 
@end 

文章二传手然后可以覆盖相应地更新视图,就像这样:

- (void)setArticle:(Article *)newArticle { 
    _article = newArticle; 
    self.titleLabel.text = _article.title; 
    self.bodyLabel.text = _article.body; 
} 

所以我的问题是,这在OO和iOS/MVC最佳实践方面,这两个选项中的哪一个最好?

我当然看到这两个被使用。我在UITableViewCell子类中见过OPTION 2。

我也读了视图和模型的设计应是可重复使用的,而不是依靠什么而视图控制器是为了是最可重复使用的一群。

我的直觉是使用选项1,只是因为我宁愿视图控制器做结合的模式,认为肮脏的工作,让模型和视图保持独立,不知道对方。但是,由于一些观点只是为了做一件事而设计的,所以将它们直接绑定到特定的模型可能并不是那么糟糕。

我很想听听你对这个意见。

+0

选项2更好。因为视图和模式似乎在那里有特定的工作,不需要重复使用。所以你不应该在管理员课上做他所有的混乱工作。使其灵活轻便。 – Divyu 2013-05-13 07:14:39

+1

选项1是更好的设计。但我更经常地使用选项2,因为#1它更容易,#2更少(重复)代码,#3我不认为我会在其他地方重复使用这个类 – 2013-05-13 07:14:58

+1

根据我的经验,带有模型引用的视图是*大量*痛苦的屁股调试/理解。当我回到使用它们的旧代码时,需要很长时间才能确定到底发生了什么。 – sapi 2013-05-13 07:15:00

回答

29

这并不总是一个或者或者决定。你的第一个选择更典型的是Apple的MVC版本;在iOS中,模型和视图通常不是直接相互对话,而是控制器完成大部分的协调。然而,拥有一个知道更大模型中特定类的自定义视图并不是不合理的。您可能会有一个知道如何处理文章的ArticleView,但ArticleView应该仍然会收到它从控制器显示的任何文章,而不是直接从较大的模型中获取文章。

MVC的目标之一是使模型和视图类更加可重用。如果你保持你的ArticleView非常简单,那么控制器必须完成所有解释文章的工作,那么你实际上可能会失去可重用性 - 每次你想用一个新的视图控制器重用ArticleView时,你必须重现所有解释ArticleView文章的代码。或者,您始终使用相同的视图控制器类来管理ArticleView。这些都不是“可重复使用的”。

与此同时,您必须承认,ArticleView和ArticleView之间存在某种自然耦合,因为ArticleView旨在显示文章的所有相关详细信息,无论它是直接从文章中获取它们或者由视图控制器设置它们。如果文章发生变化,ArticleView将不得不改变是否知道文章的可能性很大。

因此,尽管文章可能是一个模型类,但可以有一个知道它的视图是可以的。你不想要的是一个ArticleView,它知道更大的模型,并试图从模型本身获取文章。这将您可以在ArticleView中显示的文章限制为仅在ArticleView看起来可以找到的那些文章 - 它会阻止您显示其他来源的文章。

+1

很好想过。 @Caleb有钉。 – aLevelOfIndirection 2013-05-13 07:44:43

+1

我同意一个可重用模型,但是您创建了多少次可重用视图?不能很多,当然? – PeteH 2013-05-13 07:47:01

+0

@PeterH即使在单个应用程序的上下文中,可重用性也有所不同。例如,OP的应用程序的第2版可能会添加创建新文章的功能,或者可能会存储一组最喜欢的文章。知道如何使用高于数据的字符串和数字填充自己的视图可以真正简化事情。 – Caleb 2013-05-13 13:15:11

-1

选项1是MVC。选项2不是。

OO是在不同的级别真的,你有一个模型对象,视图和控制器,所以你不能做更多的是面向对象的。

这两个选项当然可以工作,但MVC的存在是有原因的(我相信你已经完成了一些常规阅读like this),你会发现如果你的代码更易于阅读,理解和重用遵循MVC的原则。

+1

您是否阅读过该链接?架构图显示模型和视图之间的耦合。首先介绍MVC作为概念的JOT文章描述了模型和视图之间的耦合。 MVC上的Apple文档声明“视图对象通常与MVC应用程序中的模型对象分离”,这很难断言MVC按照定义在模型和视图之间解耦。声明“选项1是MVC。选项2不是”。是完全没有根据的。 – 2016-05-29 19:08:07

1

坦率地说,有时我自己做选项2。但选项1“不在书中”。

2

是的,你已经证明了这个问题的理解。

选项1是MVC的经典结构,我推荐它作为你提供的两个默认路由。

仅仅因为选项1是一个更纯的定义,并不意味着它需要应用于任何可能的地方。

我做出的最常见的偏差是当一个实现是如此特定并且没有重用时,引入一个专用的控制器类型只会导致更多的代码来编写和维护实现很小,非常专业化,不可重用,并且不会大幅增长。如果程序很适合将V和C折叠成一个单独的实现并适合某些小的代码(例如几十行代码),我不担心使用选项2.

现实比但是要点是:不要觉得你需要坚持#1,尽管你可能不会理解在2年前编写和维护一些中等规模的程序之前,如何使用#2可以引入维护问题。从一个到另一个可以在一个已发货的程序中引入许多变化 - 本来可以避免的。

选项2的使用应该是少数。如有疑问,请使用选项1。

无论哪种方式,我相信模型不应该知道视图或控制器。

对我来说,在编写可重复使用的组件时,严格遵守更重要。

+1

+1表示M不应该知道V或C.M可能是可重复使用的,V和C的可能性更小 – PeteH 2013-05-13 07:46:07

0

正如其他人所说,选项1是更纯粹的方法。控制器应该是视图和模型之间的“接线盒”。

然而,这种类型的方法(例如微软称为MVC的框架)的一些实现丰富了选项2.当然,在微软的情况下,View和Model相互了解的事实允许IDE创建大量的样板代码,并为您节省“麻烦”。这样做的好处是你花时间写“功能”代码而不是“接线”代码。所以,纯粹与否,你可以欣赏他们来自哪里。

正如软件开发中经常发生的那样,选项1和选项2之间的选择归结为纯粹性与实用性。

1

在苹果公司关于这个主题的官方指导方面,在Objective-C编程的概念的MVC as a Compound Design Pattern部分文件讨论了这两种方法,但清楚地阐明了苹果的选项1的优先级高于你的选择2.实际上Cocoa Core Competencies只列出了选项1.

我从来没有后悔实施选项1的方法,但是当我偷工减料并且试图让模型和视图直接交互时,我经常后悔当我不得不去在稍后的日期返回并修改系统。

+0

感谢您分享您的经验。通常,大型项目的个人经验比文档更有价值。 – nebs 2013-05-13 18:04:53

相关问题