How to implement a complex NSDocument-based app th

2020-07-22 20:23发布

问题:

I'm working on an app that supports a very complicated set of operations. It's akin to something like Xcode, in that the main document is represented by something like a project window, with numerous entries in it. The document on disk is a bundle (meaning a directory with a file & folder structure underneath).

There is at least one file type that it can import and export (.mfst), but it's not intended to directly edit this file type. That is, opening this file type results in a native document type being created, and the contents of the file being imported into it. The on-disk file is a bundle (.mproj) with numerous files contained within it.

Technically, that file is copied verbatim into the proper location inside the native document bundle. Any changes to the data contained in that file are saved into the copy in the bundle, not the copy that was imported.

That file type can be exported, too.

Question 1: Is this app a Viewer of the imported type, or an Editor? I think it's the former.

Question 2: This question on supporting imported types shows how to implement import via the NSDocument subclass, but it seems that perhaps subclassing NSDocumentController is a good way to go.

One reason for this is that if the user has already imported a .mfst file, I want to catch that fact. There are other files that might be related to an open document, and should import into that document rather than creating a new one.

Question 3: Unfortunately, some of the code to operate on the project requires that certain files exist on disk. This means that even when a new document is created in response to opening the importable file type, I need to go ahead and create the bundle on disk and copy the file there so it can be operated on. I'd like to maintain the illusion to the user that this is an untitled, unsaved document. Is that possible?

I realize this goes against Apple's "modern" notion of documents that don't need to be saved. Maybe it would be better to just have all operations auto-save. I know I've never been comfortable not being able to explicitly save a document. I'm not actually sure what the recommended UI is these days (Apple seems to have reversed course on this).

Recommendations welcome.

回答1:

  1. The behaviour sounds like a Viewer of the original file because it can not alter the file.

    For exported file types, add these to your application's Info.plist file using the UTExportedTypeDeclarations key value. An example from Font Pestle is below. Font Pestle does not open or edit CSS, but it does export the format:

     <key>UTExportedTypeDeclarations</key>
         <array>
             <dict>
                <key>UTTypeConformsTo</key>
                <array>
                    <string>public.source-code</string>
                    <string>public.utf8-plain-text</string>
                </array>
                <key>UTTypeDescription</key>
                <string>Cascading Style Sheet</string>
                <key>UTTypeIdentifier</key>
                <string>eu.miln.font-pestle.css</string>
                <key>UTTypeReferenceURL</key>
                <string>http://www.w3.org/Style/CSS/</string>
                <key>UTTypeTagSpecification</key>
                <dict>
                    <key>public.filename-extension</key>
                    <array>
                        <string>css</string>
                    </array>
                </dict>
            </dict>
    
  2. Subclassing NSDocumentController is a reasonable place to check for previously imported copies of the file being opened.

    If you find yourself writing hundreds of lines of code in your NSDocumentController subclass, reconsider your design. The subclassing required should be minimal.

  3. Use NSDocument's support for NSFileWrapper.

    NSFileWrapper is designed to help ease the managing bundle based documents. NSDocument and NSFileWrapper will handle saving temporary copies of your untitled documented before the user actively saves or needs to pick a destination for the document.

I highly recommend reading Apple's About the Cocoa Document Architecture and following its guidelines as closely as possible. This will save you time and, hopefully, make maintaining your application easier as Apple evolve their underlying frameworks.