Yes, I missed that NSNavLastRootDirectory default.  That explains the magic.

Also, I’d forgotten about -[NSSavePanel setDirectoryURL:].  TextEdit does not 
invoke this method, so that does not explain the behavior.  And yes I agree 
that overriding both -runModalOpenPanel:forTypes: and 
-beginOpenPanel:forTypes:completionHandler:, calling super, is even simpler and 
safer than re-implementing -openDocument:.

So I tried that.  But it didn’t work either!  Not even in the TextEdit sample 
project.  The dialog always opens to either the default NSNavLastRootDirectory 
value, or ~/Documents, or TextEdit’s folder in iCloud Drive.

The workaround is to ignore the documentation, and instead set 
NSNavLastRootDirectory in NSUserDefaults standardUserDefaults.  I tried this in 
several different scenarios and it *never* fails.  Code is below.

My actual app is a “semi-shoebox” app.  It is document based, but most use only 
a single document, which I place for them into ~/Library/Application Support.  
But advanced users can create multiple documents.

I think that this all “just worked” before 10.9, when the directory became 
inscrutable and unpredictable.  I’d tinkered with this several times since 
then; actually I remember trying -setDirectoryURL:, but I could never figure 
out what it was doing, and it was not a big enough issue to take the time to 
get to the bottom of it, as we now have.  Thank you, all.

I’ve filed Bug 19496899 on the two methods that don’t work, suggesting that 
-[NSDocumentController currentDirectory] be marked as deprecated or ignored.  
For outsiders, the bug is here:

http://openradar.appspot.com/radar?id=6280770725347328

Jerry

Workaround is to add this code to NSDocumentController subclass:

/*!
 @details  Your implementation of this method may vary.
 */
- (NSString*)currentDirectory {    
    // Start with the parent of the frontmost document, if there is one
    NSDocument* document = [self currentDocument] ;
    NSString* answer = [[[document fileURL] path] 
stringByDeletingLastPathComponent] ;
    
    if (!answer) {
        answer = [self shoeboxFolder] ;
    }
    
    if (!answer) {
        // What the hell
        answer = [super currentDirectory] ;
    }
    
    return answer ;
}

- (void)patchOpenPanel:(NSOpenPanel*)openPanel {
    // The following call should work, according to the documentation, but
    // it does not; at least in 10.10 and, if I recall correctly, 10.9.
    [openPanel setDirectoryURL:[NSURL fileURLWithPath:[self currentDirectory]]] 
;
    // The following call should not work, but it does.
    [[NSUserDefaults standardUserDefaults] setObject:[self currentDirectory]
                                              forKey:@"NSNavLastRootDirectory"] 
;
}

/*!
 @details  This method is probably not called in recent OS X versions, but
 the documentation is confusing and I'm not sure, so I'm overriding it anyhow.
 */
- (NSInteger)runModalOpenPanel:(NSOpenPanel *)openPanel
                      forTypes:(NSArray *)types {
    [self patchOpenPanel:openPanel] ;
    return [super runModalOpenPanel:openPanel
                           forTypes:types] ;
}

/*!
 @details  This method is called by -openDocument:
 */
- (void)beginOpenPanel:(NSOpenPanel *)openPanel
              forTypes:(NSArray *)inTypes
     completionHandler:(void (^)(NSInteger result))completionHandler {
    [self patchOpenPanel:openPanel] ;
    [super beginOpenPanel:openPanel
                 forTypes:inTypes
        completionHandler:completionHandler] ;
}


_______________________________________________

Cocoa-dev mailing list ([email protected])

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to