【问题标题】:How does Xcode setup a document based application?Xcode 如何设置基于文档的应用程序?
【发布时间】:2011-06-26 19:09:19
【问题描述】:

我正在学习 Cocoa,通过阅读文档我的理解是,当应用程序启动时会发生以下情况:

  1. 已创建共享应用程序实例。
  2. 从应用程序属性列表中查找主 nib 文件,以便应用程序知道要加载哪个 nib。
  3. 运行循环已启动。

这很好,对单窗口应用程序有意义,但是我对创建 基于文档的应用程序时 xcode 所做的事情感到困惑。

在这种情况下,有两个 nib 文件;第一个包含应用程序菜单,第二个包含代表 NSDocument 子类的窗口。当我运行应用程序时,会自动打开一个新的文档窗口。

根据我对上述应用程序工作原理的理解,我不明白我的应用程序如何知道在从属性列表中查找菜单笔尖后打开文档窗口。据我所知,没有生成任何代码来执行此操作(除了 windowNibName 方法,但它是从哪里调用的?)

谁能告诉我 xcode 的不同之处在于应用程序知道它是基于文档的,因此需要打开一个文档窗口?

更新:

我想了解的是,如果我的应用程序设置为基于文档的应用程序而不是单个窗口应用程序,Xcode 是如何知道如何做一些不同的事情的。据我所知,没有设置来指定这一点,而且 Xcode 似乎没有生成任何代码来提供这种不同的行为。

通过阅读过去几天的文档,我认为我知道这是如何工作的,但不确定:

  1. _NSApplication_有一个委托方法applicationOpensUntitledFile,由应用程序委托调用。
  2. NSDocumentController 默认设置为应用程序委托,默认实现会查找 CFBundledTypeInfo 的存在以确定文档是否基于文档,并根据需要做出响应应用程序(即基于文档的应用程序是 YES,单窗口应用程序是 NO)。
  3. 大多数情况下,在创建单个窗口应用程序时,应用程序委托会被自定义 AppController 替换,该自定义AppController 通常不会包含 applicationOpenUntitledFile 方法的定义,如它不适合应用类型。

希望任何 Cocoa 专家都可以确认我的理解是否正确,或者我是否找错了树。

【问题讨论】:

    标签: xcode cocoa xcode3.2


    【解决方案1】:

    当您创建基于文档的应用程序时,您会得到一些东西:

    • NSDocument 的子类
    • 除了 MainMenu.xib 之外,此文档的新 xib 文件
    • Info.plist 中的 CFBundleDocumentTypes 条目,它告诉应用您的 NSDocument 子类

    当您的应用打开时,共享的 NSDocumentController 将使用 CFBundleDocumentTypes 信息创建一个新的无标题文档。

    有关更多信息,请阅读The Document-Based Application Project Template 和其他基于文档的应用程序指南。

    【讨论】:

    • 所以基本上我的属性列表文件中 CFBundleDocumentTypes 条目的存在决定了 NSApplication 是否将我的程序视为基于文档的应用程序?
    • 基本上,是的。正如我所说,共享的 NSDocumentController 将使用 CFBundleDocumentTypes 创建一个新文档。
    • 如果你在-[NSDocumentController openUntitledDocumentAndDisplay:error:]上添加断点,你可以看到它被自动调用了。
    • 谢谢。我刚刚通过创建一个 NSDocumentController 子类、覆盖该方法并在其中放置一个断点来测试这一点。出于好奇,我还在一个基于非文档的应用程序中尝试了这个,看看会发生什么并且它没有被调用。不知道是不是因为单文档应用的plist中没有CFBundleDocumentType?很抱歉问了很多问题,但我真的很想在使用之前了解系统的管道是如何工作的,而不是依赖 IDE 的魔力。
    • 我认为是这样,但我不完全确定。文档描述了很多细节,但我可以理解想要了解更多。我鼓励您阅读我链接的指南。摘录:“当用户从文件菜单中选择新建时,NSDocumentController 对象从应用程序信息属性列表中的CFBundleDocumentTypes 属性中获取适当的NSDocument 子类,分配该类的一个实例,并初始化该实例通过调用NSDocument 方法initWithType:error:。"
    【解决方案2】:

    我认为你的权利。如果你创建一个非基于文档的应用程序,在 -Info.plist 中添加文档类型信息,并在 main.m 中设置 NSApplication 的委托如下

    int main(int argc, const char * argv[])
    {
        [[NSApplication sharedApplication] setDelegate:[NSDocumentController sharedDocumentController]];
        [[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:NSApp topLevelObjects:nil];
        [NSApp run];
    }
    

    行为似乎与默认的基于文档的应用程序模板相同。

    【讨论】:

      【解决方案3】:

      不,你的假设不对,看一下GNUstep版本的实现,在NSApplication的finishLaunching方法中:

      NSDocumentController    *sdc;
      sdc = [NSDocumentController sharedDocumentController];
      if ([[sdc documentClassNames] count] > 0)
      {
        didAutoreopen = [sdc _reopenAutosavedDocuments];
      }
      

      所以它会自动创建一个 NSDocumentController 的实例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多