Reputation: 11
In its documents, my application uses a lot of assets that are relative to the document path. So the document must be saved before assets can be added. How can I force-call a [NSDocument saveDocumentAs] ?
I managed to do parts of it : by creating my own document controller, and inside openUntitledDocumentAndDisplay: force a call like this :
- (id)openUntitledDocumentAndDisplay:(BOOL)displayDocument error:(NSError **)outError
{
NSDocument * res = [super openUntitledDocumentAndDisplay:displayDocument error:outError];
[res saveDocumentAs:self];
return res;
}
This forces the save dialog to appear, but unfortunately I can not check whether the user pressed cancel : the saveDocumentAs call is asynchronous and continues immediately !
Is there a way to fix this ?
Upvotes: 0
Views: 815
Reputation: 5566
NSSavePanel can run modally. Here is how it can/should look like.
- (id)openUntitledDocumentAndDisplay:(BOOL)displayDocument error:(NSError *__autoreleasing *)outError
{
Document *document;
NSSavePanel *panel = [NSSavePanel savePanel];
panel.prompt = @"Create";
NSInteger modalCode = [panel runModal];
if (modalCode == NSModalResponseOK) {
NSURL *URL = [panel URL];
NSError *docError;
document = [[Document alloc] initWithType:nil & docError];
[document saveToURL:URL ofType:nil forSaveOperation:NSSaveOperation completionHandler:^(NSError *error){
if(error) {
return nil;
}
[self addDocument:document];
[document makeWindowControllers];
if (displayDocument) {
[document showWindows];
}
}];
}
return document;
}
To sum up for reference:
override openUntitledDocumentAndDisplay
Upvotes: 0
Reputation: 281
I had a similar problem. By using: saveDocumentWithDelegate:(id)delegate didSaveSelector:(SEL)didSaveSelector contextInfo:(void *)contextInfo you can defer your processing (or not) until after the document save dialogue has completed. This means you can find out whether the user cancelled or not. You split your processing in two, do whatever preparation you need and put the rest (that depends upon a successful save) into another method. If you use something like:
[self saveDocumentWithDelegate:self didSaveSelector:@selector(actuallyDoIt: didSave: contextInfo:) contextInfo:nil];
The document will be saved but, critically, if it has not been saved before, the Save dialogue will appear so the user can input a file name. Once he/she has done that, or cancelled, your method actuallyDoIt: (or whatever) is invoked. The didSave: parameter tells you whether the save actually happened (essentially, did the user cancel) so you can either continue or offer an alert explaining politely to the user that nothing's going to happen until they save.
Upvotes: 1
Reputation: 7219
I have a similar thing in my application, in my case if the user tries to do something, I pull up a prompt to say 'This requires you to save the document first' with buttons to cancel or save.
If you want to absolutely force it, then instead of using saveDocumentAs, just display your own NSSavePanel. Run it modally, check the result, save the document with the result, and if this doesn;t go smoothly, call it again. You can check if the document is saved by looking for a valid value for it's file path.
Upvotes: 0