How to Initialise a New Nsdocument Instance in Swift

How do I initialise a new NSDocument instance in Swift?

Above answer works for Swift 1.

It has to be changed to answer below in Swift 2:

convenience init(type typeName: String) throws {
self.init()
// Rest of initialization code here
}

This was answered here: http://meandmark.com/blog/2015/07/nsdocument-initwithtype-in-swift-2/

Reposted for convenience since this is a common problem.

Initial app launch from storyboard fails to call NSDocument init

In your storyboard, make sure both your Window Controller and its Content View Controller have Is Initial Controller unchecked and Presentation set to Multiple in the Attributes Inspector.

Window Controller Attributes Inspector image

View Controller Attributes Inspector image

Having Is Initial Controller checked will cause the application to instantiate one window controller before any of the NSDocument/NSDocumentController "magic" happens. Presentation: Multiple should be selected for coherence, although it might not really make a difference.

Also, make sure your document types are properly setup in Info.plist, particularly the NSDocumentClass key (should contain $(PRODUCT_MODULE_NAME).Simulation).

I believe your question about autosavesInPlace is already answered in the comments…

NSDocument opening over a default document

The behavior you describe is not automatic. For an example of how to handle this situation, see the open-source TextEdit example code. Specifically, take a look at the -[DocumentController replaceTransientDocument:] implementation.

- (void)replaceTransientDocument:(NSArray *)documents {
// Transient document must be replaced on the main thread, since it may undergo automatic display on the main thread.
if ([NSThread isMainThread]) {
NSDocument *transientDoc = [documents objectAtIndex:0], *doc = [documents objectAtIndex:1];
NSArray *controllersToTransfer = [[transientDoc windowControllers] copy];
NSEnumerator *controllerEnum = [controllersToTransfer objectEnumerator];
NSWindowController *controller;

[controllersToTransfer makeObjectsPerformSelector:@selector(retain)];

while (controller = [controllerEnum nextObject]) {
[doc addWindowController:controller];
[transientDoc removeWindowController:controller];
}
[transientDoc close];

[controllersToTransfer makeObjectsPerformSelector:@selector(release)];
[controllersToTransfer release];

// We replaced the value of the transient document with opened document, need to notify accessibility clients.
for (NSLayoutManager *layoutManager in [[(Document *)doc textStorage] layoutManagers]) {
for (NSTextContainer *textContainer in [layoutManager textContainers]) {
NSTextView *textView = [textContainer textView];
if (textView) NSAccessibilityPostNotification(textView, NSAccessibilityValueChangedNotification);
}
}

} else {
[self performSelectorOnMainThread:_cmd withObject:documents waitUntilDone:YES];
}
}

If you look also at -openDocumentWithContentsOfURL:display:error: and a few other places that call the above method, you'll get a good idea of how they go about replacing a "transient document" (the "Untitled" document) with the opened document.

I hope this helps.

How do I use a subclass of NSDocumentController in XCode 4?

In your application delegate:

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

- (void)applicationWillFinishLaunching:(NSNotification *)notification {
VRDocumentController *dc = [[VRDocumentController alloc] init];
}

This will make sure that an instance of VRDocumentController is created and registered as the shared document controller, preventing Cocoa from using the default NSDocumentController.

As to why you haven’t been able to use a custom object in your nib file, make sure that that you select Object (blue cube) instead of Object Controller (blue cube inside a green sphere) when dragging a new object into the nib file.


Edit: If you’re targeting an OS X version that supports restoration, -applicationWillFinishLaunching: may be too late to register a custom document controller. If the application delegate is placed inside MainMenu.xib, it should be instantiated by the nib loading process before any documents are restored, hence you can move the NSDocumentController subclass initialisation to the application delegate’s init method:

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

- (id)init {
self = [super init];
VRDocumentController *dc = [[VRDocumentController alloc] init];
return self;
}

Getting NSDocumentController from NSDocument

You don't need an outlet or anything like that. NSDocumentController is a singleton, meaning that there's only ever one instance that manages documents for the whole app. Because you have that custom document controller in your nib, it's the first to be instantiated and therefore becomes the shared document controller. So all you have to do is retrieve the shared document controller:

In Objective-C:

MyDocumentController *sharedController = [MyDocumentController sharedDocumentController];

In Swift:

let sharedController = MyDocumentController.shared()


Related Topics



Leave a reply



Submit