I try to assign a file type to my application.
In Info.plist I add:
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>type</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>icon</string>
<key>CFBundleTypeName</key>
<string>My Project</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSTypeIsPackage</key>
<false/>
</dict>
</array>
In Main.mm:
....
-(BOOL) application:(NSApplication *)sender openFile:(NSString *)filename {
NSLog(@"Opened by file");
return YES;
}
@end
int main(int argc, char* argv[]) {
[NSApplication sharedApplication];
[[[[Window alloc] init] autorelease] makeMainWindow];
[NSApp run];
return 0;
}
But when I try double click on the my file type, The app only open with the warn: could not be opened, MyApp cannot open file in format. Also the message from NSLog is not called at all.
2
Answers
There are several issues with the code you posted but I was able to get the desired behavior with a few modifications.
I assume this is your window interface and implementation:
This is extremely odd to be using a window object as an application delegate. Normally, you have a controller object that owns and manages the window and also acts as the application’s delegate.
In any case, it’s still possible to get… well, functional behavior by changing the
main()
function to the following:There are two notable changes. First, your problem was that you didn’t set the window instance to be the application delegate. Second, IIRC, you should never call
-makeMainWindow
directly; rather, that method exists so that you can override it if you wish. If you want to display the window on screen, you call-makeKeyAndOrderFront:
.Opening a file should display the logged line in console (if you’re using Xcode 12.5.1, resize the log window if needed to workaround the display bug).
Under manual reference counting, I believe this would leak memory, since no autorelease pool is created, but I didn’t see any of the usual warnings in console. Anyway, while this code works, it results in a fairly undesirable scenario. There is no main menu in the app so to quit it you have to use the Dock. The window created is also tiny and has no resizing capabilities, etc.
EDIT: An example project is at https://github.com/NSGod/OpenFile.
The following subclass of NSWindow should allow you to save a file with a unique ‘.jaf’ extension and then reopen the file into the app by double clicking on it. The info.plist is not as critical as I initially thought; I did not alter the one created by Xcode. Most important for this non-Document based app seems to be the calling of NSApplicationDelegate method -(BOOL) application: openFile. The NSApplicationDelegate was added to the NSWindow subclass instead of having a separate AppDelegate as is usually the case. When working correctly you should hear a beep when this method is called after a .jaf file is double-clicked; I couldn’t find the NSLog output. To run the demo in Xcode first create an objc project and delete everything in the ‘main.m’ file and copy/paste the following source code into it. Delete the pre-supplied AppDelegate class to avoid duplicate symbols. In the entitlements set the App Sandbox to NO and set read-only to zero. After the JAF app has been made, use it to save a file to your desktop with the ‘.jaf’ extension. Then make a copy of the app (shown in the Finder) and copy/paste it into the Applications folder. The next step is critical; right click on the file that you just made and use either Get Info or Open With to set the file to always open with your newly made app. At this point you should be able to double click on the xxxx.jaf file and have it open into your app with an audible beep.