About | ACP | Buy | Industry Watch | Learning Curve | News | Products | Search | Substack
Home » Learning Curve » Hotspots

(A Document Being Saved By Rixedit)/CocoaDocument-Based.rtx

Small Scale Data Loss™ © Apple Inc.

Get It

Try It

Following up on yesterday's good tidings this bit of informal research looks further into what other dirty secrets are hidden in Apple's new document controller system for Leopard.

Sorry, but it's not going to be a better ride than yesterday. It's going to be worse.

Tens of thousands of Cocoa document-based applications for Apple's platform are affected.

It's previously been seen Cocoa for Leopard wreaks havoc on file system operations. What's demonstrated here is how much deeper this design flaw goes.


Cocoa document-based apps can be sent any one of a number of calls from the 'spider in the web' NSDocumentController. One of the easiest to use to inspect this behaviour further is - as before - the writeToFile: method.

-(BOOL)[NSDocument writeToFile:(NSString *)file ofType:(NSString *)type]

The client (a subclass of NSDocument) is sent the above method when the NSDocumentController knows the user wants to save a document.

The presumption up to Leopard 10.5 is that the 'file' argument would be the actual path to the file currently being edited. And in many ways this could be important information for the document to be privy to.

But it's not that way anymore under Leopard.

There are ways around this however. The NSDocument class contains a number of methods which can produce both the 'display name' of a file (that which is shown in the title bar) and the 'file name' (which is the full path to the current file).

Normally the response to the above message sent by NSDocumentController would be as follows.

-(BOOL)writeToFile:(NSString *)file ofType:(NSString *)type {
    return [textString writeToFile:file atomically:0 encoding:encoding error:0];

The method wants only a 'BOOL' reply, indicating success or failure (with non-zero for success and zero for failure).

The document has a pointer to its own text (given above as textString) and it uses the path given by the NSDocumentController.

But we already know that starting with Leopard 10.5 this 'file' value is not a path to the actual file - but instead a temporary file hidden 'way down there' in one of the new (and many) temporary file locations on this confused system.

So what happens if we try to intercept this API and write it our own way? What is going to happen if we disregard the file path given us by NSDocumentController and simply write to the real file that already exists sat the real path? As in the following?

-(BOOL)writeToFile:(NSString *)file ofType:(NSString *)type {
    return [textString writeToFile:[self fileName] atomically:0 encoding:encoding error:0];

And we can put in an extra line in there to corroborate that the value of file is still somewhere in orbit around Neptune.

NSRunAlertPanel(@"NSDocumentController for 10.5 Leopard", file, 0, 0, 0);

Sure, we already know what's going to happen, but having it there means we can 'block' - and in the interim inspect our file system to see what else is going on thanks to the great changes in NSDocumentController for Leopard implemented by those all-wise 'engineers' in Cupertino.

[No, they have no respect for the shoulders they stand on - that's the whole point. Ed.]

First build our app with the new sneaky code put in. Then launch the application and open an existing document.

Now save it. You get our interim dialog to tell you what's going on.

And when you click OK here your NSDocumentController should be already off the hook. After all, you have the right to save your file to any location you want, don't you?

Are you sure?

And why is that? Check back with your file system again. Your original file is gone! Your loving NSDocumentController for Leopard already removed it!


These things are never documented by Apple. Developers - and much less users - have no inkling what's going on. They're expected to discover these things after the fact and just accept them - and just intuitively trust that the Apple engineers have a good reason for these obnoxious changes and that all will be for the best.

But these changes are neither documented nor justified, and they're certainly not for the best.

Cast your memory way back to the scary stories of 'massive data loss'. Try to remember how it was discovered Apple code would load entire gigabyte files in memory for transfer across a network and would delete the originals before verifying the transferred copy had in fact arrived intact. Try to remember how nutballs like Dilger tried (!) to justify this aberrant behaviour on some wild premise. Try to remember how enterprise networks suffered the type of data loss no professional shop powered by software from any other company has ever had to endure.

Now see the behaviour of NSDocumentController as a microcosmic variant of the massive data loss design flaw. Once again they're destroying your original documents before they've even begun updating or copying them, much less waiting for completion and verifying all went well.

There is no programmatic reason in all of computer science to do things in this 'unsafe' sequence. With every file operation you perform, with every 'file save' you make in any one of thousands of Cocoa applications for OS X 10.5 Leopard, Apple are jeopardising your data and putting you at risk of losing everything.

Massive data operations or everyday document editing, Apple engineers continue to prove they don't have what it takes.

See Also
Hotspots: Leopard -Tmp-
Developers Workshop: Y.G.B.K.
Hotspots: Just An Ordinary Innocent Little Old Text File
Hotspots: (A Document Being Saved By Rixedit)/Untitled
Rixstep/7: '(A Document Being Saved By Rixedit)/Untitled' (Membership Required)
Rixstep/7: '(A Document Being Saved By Rixedit)/CocoaDocument-Based.rtx' (Membership Required)

About | ACP | Buy | Industry Watch | Learning Curve | News | Products | Search | Substack
Copyright © Rixstep. All rights reserved.