Reputation: 4239
I'm developing a macOS application for editing files, but am getting a rather annoying error when trying to use NSDocumentController.shared.makeDocument
to create a new NSDocument
instance from a file URL.
Below is a simple example of how I am calling makeDocument
. The file test.md
exists on disk.
let url = URL(fileURLWithPath: "/Users/me/Desktop/test.md"
do {
let newDocument = try NSDocumentController.shared.makeDocument(withContentsOf: url, ofType: url.pathExtension)
print("Created \(newDocument)")
} catch {
print("Error: \(error)")
}
The problem is that this try
call fails and it reaches the catch
block. The error I get is:
Error: Error Domain=NSCocoaErrorDomain Code=256 "“test.md” could not be handled because MyApp cannot open files in the “md” format." UserInfo={NSLocalizedDescription=“test.md” could not be handled because MyApp cannot open files in the “md” format., NSLocalizedFailureReason= MyApp cannot open files in the “md” format.}
I believe i've correctly set my app's Document Types for markdown files as shown below:
I've tried cleaning the build , removing derived data and also adding an 'Imported UTI' type for markdown files but nothing seems to work.
The strange thing is that via File > Open, I am able to open .md
files, just not programatically via makeDocument
.
Upvotes: 1
Views: 2089
Reputation: 11337
I ran into this issue for the millionth time just now.
I was trying to create an ObjC Mac app that opens CSS documents, but I didn't realize I was using the wrong "identifier" for the CSS document type in my Info.plist.
Here's how I discovered the root problem and fixed it.
I first overrode and set a breakpoint in -[NSDocumentController documentClassForType:]
to discover what the exact typeName
is that was failing to create an instance of my NSDocument
subclass (Document
in my case):
Inspect the typeName
argument there. In my case, it was public.css
.
Now go to edit your App Target and click on the Info
tab.
Expand the Document Types
item and find the document type you are having problems with (CSS in my case).
Make sure the value in the Identifier
field matches the value you just inspected while debugging the -documentClassForType:
method (in my case public.css
).
These must match. I had the wrong value here (in my case, I had org.w3.css
, which is wrong).
Upvotes: 0
Reputation: 622
makeDocument(withContentsOf:ofType:)
expects a type as second parameter, not an extension. Have a look at typeForContents(of url: URL)
on how to derive the type from an URL.
See Figure 6-3 in https://developer.apple.com/library/archive/documentation/DataManagement/Conceptual/DocBasedAppProgrammingGuideForOSX/AdvancedTopics/AdvancedTopics.html
And as Marek H pointed out in his answer, in the info.plist there should be an UTI (identifier) for the document type.
Upvotes: 2
Reputation: 5576
Verify generated Info.plist with example from XCode 10 Info.plist and their settings. Also check lsregister command and see if your app is registered to handle md.
lsregister (use switch dump or read man):
/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister
Markdown document:
<dict>
<key>CFBundleTypeName</key>
<string>Markdown Document</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>md</string>
<string>mdown</string>
<string>markdown</string>
<string>text</string>
</array>
<key>LSItemContentTypes</key>
<array>
<string>net.daringfireball.markdown</string>
</array>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleTypeIconFile</key>
<string>net-daringfireball-markdown</string>
</dict>
Upvotes: 1