Search code examples
swiftnsdocument

NSDocument opening over a default document


I'm writing a NSDocument-based application in Swift. I have set it to open a default document if the application is not started with a document parameter.

I've noticed that if I start the app and then immediately open another document, say using Open or Recent, the Untitled default document remains, even if it is untouched.

I was under the impression that in this workflow, the Untitled document was considered "accidental" and should be removed. Is this correct? If so, should I remove this window manually, or is there a setting I have overlooked?


Solution

  • 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.