CocoaDev

Edit AllPages

(From mailing-list posts by Dan Bernstein and Mark Piccirelli)

Q: In my document-based application, I want to replace the “Do you want to save changes…” sheet with one of my own, but to maintain the exact same behavior. How do I do it? (I tried overriding canCloseDocumentWithDelegate: to no avail). I want my NSDocument subclass to override canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo: in order to replace the “Do you want to save changes…?” alert with different phrasing and options (for example, see how Terminal.app or Mail.app behave when you try to close a dirty window).

According to the docs, the default implementation displays the alert sheet, and after the user makes a choice, calls the delegate’s shouldCloseSelector with an appropriate value. My problem is, of course, that the method that handles the user’s response to the sheet (the didEndSelector) doesn’t know what delegate and selector were given to canCloseDocumentWithDelegate:.

I can find a way to stick this in the contextInfo, but that seems ugly. How is this supposed to be done? Better yet, how does the default implementation do it?

A: Replacement of the “Do you want to save the changes…” alert is not one of the customizations of NSDocument we’ve anticipated, so it’s no fun to do, but I think there is a way to do it that’s not likely to break when run against future Mac OS X releases.

It sounds like you really should override -[NSDocument -canCloseDocumentWithDelegate:shouldCloseSelector:contextInfo:]. Here’s some sample code to walk you through it. It’s very similar to what NSDocument itself does. You have to override the method itself, provide another method that will be invoked after the alert sheet has been dismissed, and declare a context structure just to remember a little bit of stuff while the sheet’s being presented. I haven’t actually compiled this code, so anything that looks like a typo probably is.

typedef struct { id delegate; SEL shouldCloseSelector; void *contextInfo; } CanCloseAlertContext;

}

}