我正在努力理解如何更好地实现模型-视图-控制器设计模式。
什么对象应该"拥有"模型对象?单个控制器应该实例化(拥有)模型对象吗?
下面是一个示例场景:
我有一个UITabbarController包含两个uiviewcontroller (controllerA和controllerB)。显然,这两个控制器彼此都不属于对方。我有一个模型对象,它包含一些数据,还执行一些网络活动。controllerA和controllerB都需要能够对Model对象进行更改。controllerB需要知道何时对Model对象进行了更改(由controllerA进行更改或从网络活动返回结果)。摘自最近的阅读:
- 我需要模型对象和控制器b之间的KVO ? Model对象应该是单例吗?这样两个控制器都可以修改它?
- 在更简单的应用中,我已经让viewController拥有了Model对象。是否有任何方法一个控制器实例化模型对象,但为其他控制器有写访问它?
- 我也读过关于使用应用程序委托来拥有模型对象,并允许控制器通过应用程序委托共享实例访问。这看起来有点难看——使用app委托单例来全局访问我的Model对象。让我的Model对象成为单例不是更好吗?
- 我看到有人在SO给这个链接到iPhoneDevSDK,但他的方法的原因逃避我。还是那句话,这不是让应用委托参与到本该是单例的东西中吗?
主要是两个控制器访问(写)一个模型的其他方式,除了通过模型是一个单例吗?
另外,当一个控制器拥有另一个控制器(例如在UINavigationController当根视图控制器实例化另一个视图控制器堆栈在自己的顶部),共享模型的最佳方法是根视图控制器实例化模型,并将其传递给下一个视图控制器,然后将其推到导航堆栈)?
随着项目规模的扩大,在AppDelegate中存储全局对象会变得非常难看。
问问你自己:这个模型对象和我的应用程序中的其他对象之间的关系是什么?是1对1还是1对n的关系。如果您只需要一个模型就可以被各种对象访问,那么就使用单例方法。如果您需要一个对象恰好有一个模型,那么在该对象中保留一个指向该模型的指针。
当面对不同但计算正确的设计方案时,需要考虑以下几个方面
- 哪种方法可以最小化代码行?
- 哪种方法导致最少的耦合和语义耦合?
- 从一个新加入项目的程序员的角度来看,哪种方法更容易理解、维护,更不容易在无意中引入bug。
如果你开始将全局模型滚动到AppDelegate中,你最终会创建一个难以理解和维护的整体类。如果你在每个控制器中创建一个指向模型的指针,你必须在每次实例化一个新控件时传递一个对该模型的引用,并且它必须向下传递指针到它实例化的任何需要的对象。实际上,您创建了一个传递相同指针的级联瀑布,使接口文件和构造函数变得臃肿。想象一下,如果您需要跟踪5个模型对象,而不是1个模型。对象有5个指针5个模型需要传递给构造函数每次有意义吗?这是如何使你的项目有bug和不可维护的。
如果它不是很明显。AppDelegate只是一个单例。当你在应用委托中滚动所有模型时,你并没有避免使用单例,你只是创建了一个整体模型。
关于KVO:这取决于你想要完成什么。我将给出一个KVO有用的例子。假设您有一个模型对象来存储应用程序的用户首选项。
@interface SettingsModel
.....
@property (nonatomic, retain) UIColor * backgroundColor;
@end
应用程序中的其他视图应该在此设置更改时立即更新其背景颜色。这可以使用KVO:
轻松解决。[[SettingsModel getInstance] addObserver:self forKeyPath:@"backgroundColor" options:0 context:nil];
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:@"backgroundColor"]){
self.view.backgroundColor = [[SettingsModel getInstance] backgroundColor];
}
}
模型可以被多个控制器引用。想要深入了解iPhone开发中模型-视图-控制器的基础知识,请浏览斯坦福大学iPhone开发课程的前两个讲座(iTunesU免费提供,参见斯坦福大学http://www.stanford.edu/class/cs193p/cgi-bin/drupal/的信息)似乎有更多的方法可以让控制器了解视图和/或模型更新。
我不知道为什么你被困在一个单例,我也不认为在制作一个单例模型对象的问题。我认为你还需要考虑线程安全和内存泄漏。