如何在XCode 4中使用NSDocumentController的子类?

Luk*_*ger 11 cocoa objective-c xcode4

我目前正在尝试自学Cocoa开发.为此,我购买了一本非常出色的书,即适用于Mac OS X的可可食谱:佛蒙特食谱,它开始创建一个示例应用程序.它非常好,但它是针对XCode 3.2而不是XCode 4编写的.到目前为止,我已经能够自己解决这个问题,但是我遇到了一个无法弄清楚如何遵循指令的问题.

本质上,本书通过子类化的示例案例,NSDocumentController以便应用程序可以处理两个(最终可能是任意数量)不同类型的文档,因此它为每种类型打开适当的窗口.所以,我已经创建了一个自定义子类NSDocumentController(本书调用了VRDocumentController),现在我需要使它在应用程序启动过程中相对较早地加载此控制器的实例.基本上,类是单例,因此我必须在应用程序实例化标准类之前实例化我的,这必须在过程的早期完成.很公平.

本书引用Apple文档来继承NSDocumentController,该文档声明有两种方法可以解决问题:在MainMenu.xib文件中实例化类或在-applicationWillFinishLaunching:委托方法中实例化类.Apple文档没有明确说明如何执行这些操作(稍后会详细介绍),本书仅涵盖第一个版本,我认为这可能是我首选的方法.

我的问题:我不能为我的生活在XCode 4中解决这个问题.本书为XCode 3.2提供的说明不再准确,因为Interface Builder现在已经改组为XCode本身和新版本的"类选项卡"不再显示我的项目的课程.我发现Stack Overflow上的这个问题提出了类似的问题,所以我试着按照那里接受的答案.但是,当我打开Identity Inspector并尝试键入时VRDocumentController,它只会发出哔哔声并且不会接受它.我写的其他控制器类似乎都不是可接受的输入.

我也很乐意去另一条路线; 在-applicationWillFinishLaunching方法中实例化副本.但是,我不知道该方法实际属于哪个类,或者它的返回类型是什么.我也做了非常微不足道的搜索,没有运气.

小智 13

在您的应用程序委托中:

// LukeAppDelegate.h
#import "LukeAppDelegate.h"
#import "VRDocumentController"

- (void)applicationWillFinishLaunching:(NSNotification *)notification {
    VRDocumentController *dc = [[VRDocumentController alloc] init];
}
Run Code Online (Sandbox Code Playgroud)

这将确保VRDocumentController创建并注册为共享文档控制器的实例,从而阻止Cocoa使用默认值NSDocumentController.

至于为何无法在nib文件中使用自定义对象,请确保在将新对象拖入笔尖时选择对象(蓝色立方体)而不是对象控制器(绿色球体内的蓝色立方体)文件.


编辑:如果您的目标是支持恢复的OS X版本,-applicationWillFinishLaunching:则注册自定义文档控制器可能为时已晚.如果应用程序委托放在MainMenu.xib中,那么在恢复任何文档之前,它应该由nib加载过程实例化,因此您可以将NSDocumentController子类初始化移动到应用程序委托的init方法:

// LukeAppDelegate.h
#import "LukeAppDelegate.h"
#import "VRDocumentController"

- (id)init {
    self = [super init];
    VRDocumentController *dc = [[VRDocumentController alloc] init];
    return self;
}
Run Code Online (Sandbox Code Playgroud)


zak*_*ces 6

标记正确的答案(@ Bavarious'answer)无法在基于文档的应用程序上工作,因为文档通常在applicationWillFinishLaunching:调用之前加载.在阅读了@Graham Perks答案中的有用线索之后,我尝试了几种不同的方法,这似乎可靠地工作:

@implementation AppDelegate

- (id)init
{
    self = [super init];
    if (self) {
        MyDocumentController *dc = [[MyDocumentController alloc] init];
        if (dc) {};
    }
    return self;
}
Run Code Online (Sandbox Code Playgroud)

注意显然(如果尚未创建)您需要先自己创建一个AppDelegate并将其链接到MainMenu.XIB中.


Les*_*win 5

获取及时创建自定义文档控制器的更简单方法是实现该+ (void) load方法:

这实际上是您实现自定义文档控制器所需的全部内容.

@implementation AppDocumentController

+ (void) load
{
    [AppDocumentController new];
}

// ... your overriding goes here

@end
Run Code Online (Sandbox Code Playgroud)

这很酷,因为没有codez的分离.不是100%确定控制器是否过早创建,但对我来说效果很好.


Fer*_*iss 5

您可以在Swift 3中轻松子类化:

class AppDelegate: NSObject {
    let docController = DocController()
}

class DocController: NSDocumentController {
}
Run Code Online (Sandbox Code Playgroud)