开发者

Single Document Interface document based cocoa application

Is there a way to create Single Document Interface (SDI) document based cocoa application? I dont want user to open multiple d开发者_如何学Cocuments at once.


You can do this, it isn't too bad.

General approach: Use the NSDocument you have to attach itself to a singleton NSWindowController, which is the xib of your app. You can even have other stuff in that window when there are no documents open. This design works great for me, as I kept all NSDocument features in play, etc...

Here goes with some more detail:


Remove any other windows

You will use a new window, so remove any that might be default in your app template created by Xcode. Perhaps in your MainMenu.xib, get rid of that all, or move it to your new xib.

Create a new xib (window) for your future NSWindowController

Just create a placeholder for testing, later we will add way more to it (as it is our main window the user will always see).

Create your own NSWindowController, make it a singleton

So, inside your NSWindowController, create a singleton wrapper that loads your xib (only once), and returns this single singleton anytime it is called. I used a helper #define, look here for more info: https://gist.github.com/1057420

+ (id) singletonInstance {
    DEFINE_SHARED_INSTANCE_USING_BLOCK(^{
        return [[self alloc] initWithWindowNibName:@"yourxibfilename"];
    });
}

Modify your NSDocument so that it attaches to only this singleton window

Add something like this to your NSDocument based document. Basically you will tell the Document to use the singleton window that you have, and the internal setDocument inside the NSWindowController should be called automatically to replace any existing NSDocument it is showing.

- (void)makeWindowControllers {
    ReceiptDocumentWindowController *wc = [ReceiptDocumentWindowController singletonInstance];
    [self addWindowController:wc];
}

Consider removing the NSDocument from the NSWindowController on close, just to be sure it doesn't hang around. I don't think this is required in some cases, but you may investigate this as well. So, also inside your NSDocument document:

- (void)close {
    [self removeWindowController:[ReceiptDocumentWindowController singletonInstance]];
    [super close];
}

Test - You should now have a prototype solution working

There will be a few problems with it, and those all depend on your exact requirements.

First, you may consider using your own NSDocumentController to automatically close any open documents before opening a new one. You will need to research more on this.

Back to that NSViewController i mentioned, and how to update it with the "current open document". I put some glue in the NSWindowController to setDocument to attach any document that opens to my downstream IBOutlet connected xib instances (like this NSViewController). Ok, like this:

- (void)setDocument:(NSDocument *)lDocument {
    [super setDocument:lDocument];
    if (lDocument != nil && self.receiptDetailViewController != nil)
        self.receiptDetailViewController.representedObject = lDocument;
}

Now, the represented object in my NSDocumentViewController has views that bind using cocoa bindings to the NSViewController.representedObject. So, bingo, it renders my stuff almost like magic. I would recommend encapsulating like this, so you can then focus on presenting the document with the views in the xib, and the NSViewController that has a reference now to any document that gets opened.

If this is not clear enough, let me know. I will post more code. Good luck, let me know if this helps.

Marcus Williford


You should be able to obtain the UI you want by making a new Xcode project based on the Cocoa Application template, make sure you uncheck "Create Document-Based Application".

You will have to write the Open/Save commands yourself, and change your classes from NSDocument and friends, but it should be doable.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜