如何使用Interface Builder将'M'放在MVC中

时间:2009-06-10 01:35:09

标签: iphone cocoa-touch interface-builder

我同意What's the best way to communicate between view controllers?给出的答案,但是如果我使用Interface Builder来设计我的应用程序视图呢?

不使用Application Delegate,如何从Controller对象中引用Model对象?

据我所知,我不能使用依赖注入的自定义Init方法将对模型的引用传递给IB。

请原谅我,因为我觉得我在这里缺少一些非常基本的东西。我查看了IB的Apple文档,但没有找到明确的答案。

3 个答案:

答案 0 :(得分:3)

你的参考文章是一个很好的文章 - 就像你我喜欢将一个模型注入控制器(Smalltalk时代的旧习惯 - 特别是Dolphin Smalltalk非常广泛地遵循这种模式)。

我发现我的大多数控制器都有如下的init方法:

- (id)initWithItem:(id<Nameable>)item addingTo: (id<ModelContainer>)model {
    if (self = [self initWithNibName:@"ItemEditTableToolbarView" bundle:nil]) {
        self.namedItem = item;
        self.container = model;
    }

    return self;
}

然后你可以这样打电话给你的控制器:

ReDoListEditController *itemViewController = [[ReDoListEditController alloc] initWithItem: item addingTo: model];
    [self.navigationController pushViewController: itemViewController animated: YES];
    [itemViewController release];

请注意,我在init方法中嵌入了我的Nib文件的名称(如果你需要更多的灵活性,你可以创建另一个参数 - 但我还没有发现我的任何控制器都需要通用。这很有趣 - 就像在Dolphin中一样,控制器(和它们的视图)可以是非常合成的 - 通常在你的init方法中,你会从你的模型中挑选出子模型并为你的子组件调用init。我认为这可能是在iPhone上IB但我还没有探讨过这个想法。

然而你需要做一些额外的工作才能将模型传递给第一个控制器(这是我最初没想到的)。

  1. 在XCode中创建一个基于窗口的应用程序(如果你想要基于导航的应用程序,你可以很容易地用代码添加它)
  2. 编辑“YourAppDelegate.m”并将applicationDidFinishLaunching:方法更改为以下内容:

    viewController = [[AppRootViewController alloc] initWithModel:[application model]]; viewController.view.frame = [[UIScreen mainScreen] applicationFrame];

    [window addSubview:viewController.view];

    [window makeKeyAndVisible];

  3. 如果您想使用其他项目类型,以下说明似乎也有效,但需要付出更多努力(我简化为上述内容):

    1. 删除您的MainWindow.xib文件(听起来很激进,但您想自己创建MainWindow - 您仍然可以使用IB创建所有其他视图
    2. 编辑.plist文件并删除MainWindow.xib条目(通常是最后一项)
    3. 编辑您的main.m文件并更改UIApplicationMain行(将最后一个参数替换为现有应用代理的名称) - 例如:

      int retVal = UIApplicationMain(argc,argv,nil,@“YourAppDelegate”);

    4. 编辑“YourAppDelegate.m”并将applicationDidFinishLaunching:方法更改为以下内容:

      window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

      viewController = [[AppRootViewController alloc] initWithModel:[application model]]; viewController.view.frame = [[UIScreen mainScreen] applicationFrame];

      [window addSubview:viewController.view];

      [window makeKeyAndVisible];

    5. 我在UIApplication中添加了一个类别方法:

      - (MyModel *)model;
      

      然后,您可以从应用程序中获取模型(如上所示)以及应用程序中的其他位置,例如

      viewModel = [[UIApplication sharedApplication] model];
      

      虽然如果你像我所描述的那样总是将它传递给你的视图控制器,这可能是代码味道。

答案 1 :(得分:1)

InterfaceBuilder表示MVC模式中的V.因此,您不会使用您在IB中创建的任何操作来操纵模型。您将在IB创建的笔尖和模型之间使用某种委托。该委托在MVC中代理C,并且可以与用户界面以及底层模型进行通信。

答案 2 :(得分:0)

通常你不会直接在IB中触摸模型。您可以使用控制器连接视图,也可以将控制器的某些属性绑定到视图。然后编写代码(在控制器中)来访问模型。如果愿意,可以使用awakeFromNib方法,但也可以在控制器中实现自定义init。