假设我们有以下课程:
查看
@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
选项1
选项2
在选项2中,必须更改ArticleView以保存对模型的引用:
@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最佳实践方面,这两个选项中哪一个最好?
我当然看到两者都被使用了。我见过OPTION 2在UITableViewCell子类中常用。
我还读过,视图和模型应该被设计为可重用而不依赖于任何东西,而视图控制器应该是最不可重复使用的。
我的直觉是使用OPTION 1只是因为我宁愿视图控制器执行将模型绑定到视图的脏工作,让模型和视图保持独立并且彼此不知道。但是,由于某些观点只是为了做一件事,所以将它们直接绑定到特定模型也许并不是那么糟糕。
我很想听听你对此的看法。
答案 0 :(得分:30)
这并不总是一个或两个决定。你的第一个选择是更典型的Apple版MVC;在iOS中通常是这样的,模型和视图不会直接相互通信,并且控制器完成它们之间的大部分协调。但是,拥有一个知道大型模型中特定类的自定义视图并不是不合理的。您可能有一个知道如何处理文章的ArticleView,但ArticleView仍应接收从控制器显示的任何文章,而不是直接从较大的模型中获取。
MVC的目标之一是使模型和视图类更具可重用性。如果你使ArticleView非常简单,那么控制器必须完成解释文章的所有工作,那么你实际上可能会失去可重用性 - 每次你想要使用新的视图控制器重用ArticleView时,你必须重现解释ArticleView文章的所有代码。或者,您始终使用相同的视图控制器类来管理ArticleView。这些都不是“可重用的”。
同时,您必须承认Article和ArticleView之间存在一些自然耦合,仅仅是因为ArticleView旨在显示文章的所有相关细节,无论是直接来自文章还是由视图控制器设置它们。如果文章发生变化,ArticleView很可能必须改变它是否知道文章。
所以,即使Article可能是一个模型类,也可以有一个了解它的视图。你不想要的是一个ArticleView,它知道更大的模型,并试图从模型本身获取文章。这会将您可以在ArticleView中显示的文章限制为可以在ArticleView外观中找到的文章 - 它会阻止您显示其他来源的文章。
答案 1 :(得分:3)
是的,您已经证明了对该主题的理解。
选项1是MVC的经典结构,我建议将其作为两者的默认路由。
仅仅因为OPTION 1是一个更纯粹的定义,并不意味着它需要在任何可能的地方应用。
我做的最常见的偏差是当一个实现是如此具体而没有被重用时,引入专用控制器类型只会导致更多代码编写和维护,当实现很小,非常专业,不可重用,并且不会增长基本上。如果程序很适合将V和C折叠成单个实现并适合小的(例如几十行代码),我不担心使用OPTION 2.
现实比这更复杂,但要点是:不要觉得你需要坚持#1,尽管你可能不会理解使用#2如何引入维护问题,直到你编写和维护一些几年的中等规模的计划。从一个移动到另一个可以在已发布的程序中引入许多更改 - 这本来是可以避免的。
选项2的使用应该是少数。如有疑问,请使用选项1。
无论哪种方式,我相信模型不应该知道视图或控制器。
对我来说,在编写可重用组件时,严格遵守更为重要。
答案 2 :(得分:1)
坦率地说,有时候我会自己做选项2。但是选项1“不在书中”。
答案 3 :(得分:1)
就Apple关于此主题的官方指导而言, Objective-C Programming中的概念文档的MVC as a Compound Design Pattern部分讨论了这两种方法,但明确阐述了Apple对您的选项1的偏好你的选择2.实际上Cocoa Core Competencies只列出了选项1。
我从来没有后悔实施选项1方法,但是当我偷工减料并试图让模型和视图直接交互时,我常常后悔当我不得不回去修改系统时晚些时候。
答案 4 :(得分:0)
正如其他人所说,选项1是更纯粹的方法。控制器应该是视图和模型之间的“接线盒”。
然而,这种方法的许多实现(例如Microsoft称为MVC的框架)都充满了Option 2.当然,在Microsoft的情况下,View和Model相互了解的事实允许IDE创建许多样板代码,并为您节省“麻烦”。这样做的好处是你花时间编写“功能”代码而不是“连接”代码。所以,无论是否纯洁,你都可以欣赏它们的来源。
正如软件开发中经常出现的那样,选项1和选项2之间的选择归结为纯粹与实用主义。
答案 5 :(得分:-1)
选项1是MVC。选项2不是。
OO实际上处于不同的水平,你有模型,视图和控制器的对象,所以你不能做更多的事情来做OO。
这两个选项当然都有效,但MVC存在是有原因的(我确定你已经完成了一些通用的阅读like this),你会发现你的代码更容易阅读,理解和如果你遵循MVC的原则就重用。