Cocoa/iOS/iPhone中的模型对象所有权和MVC

Cocoa/iOS/iPhone中的模型对象所有权和MVC,iphone,objective-c,ios,model-view-controller,object,Iphone,Objective C,Ios,Model View Controller,Object,我试图理解如何更好地实现模型-视图-控制器设计模式 什么对象应该“拥有”模型对象?单个控制器是否应该实例化(拥有)模型对象 下面是一个示例场景: 我有一个包含两个UIViewController(controllerA和controllerB)的UIAbbarController。显然,这两个控制器都互不拥有。我有一个模型对象,它包含一些数据,还执行一些网络活动。controllerA和controllerB都需要能够对模型对象进行更改。controllerB需要知道对模型对象进行更改的时间(c

我试图理解如何更好地实现模型-视图-控制器设计模式

什么对象应该“拥有”模型对象?单个控制器是否应该实例化(拥有)模型对象

下面是一个示例场景:

我有一个包含两个UIViewController(controllerA和controllerB)的UIAbbarController。显然,这两个控制器都互不拥有。我有一个模型对象,它包含一些数据,还执行一些网络活动。controllerA和controllerB都需要能够对模型对象进行更改。controllerB需要知道对模型对象进行更改的时间(controllerA或网络活动返回的结果)。从最近的阅读:

  • 我需要模型对象和控制器B之间的KVO
  • 模型对象应该是单例对象吗?这样两个控制器都可以修改它
  • 在更简单的应用程序中,我让viewController拥有模型对象。一个控制器是否可以实例化模型对象,但其他控制器是否可以对其进行写访问
  • 我还了解了如何使用app委托拥有模型对象,以及如何允许控制器通过app委托共享实例进行访问。这看起来有点难看——使用app委托单例全局访问我的模型对象。让我的模型对象成为单例对象不是更好吗
  • 我在SO上看到有人给了iPhoneDevSDK链接,但我想不出他使用这种方法的原因。再说一次,这不是让应用程序代理参与到应该只是一个单例的事情中吗
主要是,除了通过作为单例的模型之外,两个控制器访问(写入)一个模型还有其他方法吗


此外,当一个控制器拥有另一个控制器时(例如,在UINavigationController中,当根视图控制器实例化另一个视图控制器以堆叠在其自身之上时),共享模型的最佳方法是让根视图控制器实例化模型,并在将其推到导航堆栈上之前将其传递给下一个视图控制器)?

该模型可由多个控制器引用。要深入了解iPhone开发中模型视图控制器的基础知识,请浏览斯坦福大学iPhone开发课程的前两堂课(在iTunesU免费提供,请参阅斯坦福大学的信息),似乎有更多的方法让控制器了解视图和/或模型更新


我不知道为什么你会被困在单例模型上,我也不认为制作单例模型对象有什么问题。我认为您还需要考虑线程安全性和内存泄漏。在AppDe委托中存储全局对象变得非常丑陋,因为您的项目缩放。 问问自己:这个模型对象和我的应用程序中的其他对象之间的关系是什么?是1对1或1对n的关系。如果您只需要一个模型就可以被各种对象访问,那么就采用单例方法。如果需要一个对象正好有一个模型,则在该对象中保留指向该对象的指针

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

  • 哪种方法可以最小化代码行
  • 哪种方法导致的耦合和语义耦合最少
  • 从一个新加入项目的程序员的角度来看,哪种方法更容易理解、维护,并且更难引入bug
  • 如果开始将全局模型滚动到AppDelegate中,最终将创建一个难以理解和维护的整体类。如果在每个控制器中创建指向该模型的指针,则每次实例化新控件时必须传递对该模型的引用,并且该控件必须向下传递指向其实例化的任何对象的指针。本质上,您已经创建了一个传递相同指针的级联瀑布,膨胀了接口文件和构造函数。想象一下,如果您需要跟踪5个模型对象,而不是1个模型。对于对象来说,每次都需要向构造函数传递5个模型的5个指针有意义吗?这就是如何使您的项目有缺陷且无法维护

    以防不明显。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];
         }
    }
    

    嗨,Rolf,我问的是单例,因为我不知道两个控制器(彼此都不拥有)写入同一个模型对象的其他方式。你知道怎么走吗?我看了那些讲座,谢谢。嗨,马特,不确定,课程还没结束;-)我知道cocoa没有依赖注入框架,所以现在我想说单身是可以的。谢谢lorean,很好的答案!非常感谢。