在Cocoa / iOS / iPhone中建模对象所有权和MVC



我正在努力理解如何更好地实现模型-视图-控制器设计模式。

什么对象应该"拥有"模型对象?单个控制器应该实例化(拥有)模型对象吗?

下面是一个示例场景:

我有一个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的关系。如果您只需要一个模型就可以被各种对象访问,那么就使用单例方法。如果您需要一个对象恰好有一个模型,那么在该对象中保留一个指向该模型的指针。

当面对不同但计算正确的设计方案时,需要考虑以下几个方面

  1. 哪种方法可以最小化代码行?
  2. 哪种方法导致最少的耦合和语义耦合?
  3. 从一个新加入项目的程序员的角度来看,哪种方法更容易理解、维护,更不容易在无意中引入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/的信息)似乎有更多的方法可以让控制器了解视图和/或模型更新。

我不知道为什么你被困在一个单例,我也不认为在制作一个单例模型对象的问题。我认为你还需要考虑线程安全和内存泄漏。

最新更新