如何在Mac上为我的应用程序分配文件类型



我尝试为我的应用程序分配一个文件类型。

信息。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>

在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;
}

但是当我尝试双击我的文件类型时,应用程序只打开警告:无法打开,MyApp无法打开文件格式。同时,NSLog的消息也没有被调用。

您发布的代码有几个问题,但我能够通过一些修改获得所需的行为。

我假设这是你的窗口接口和实现:

@interface Window : NSWindow <NSApplicationDelegate>
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename;
@end
@implementation Window
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
NSLog(@"Opened by file");
return YES;
}
@end

使用窗口对象作为应用程序委托是非常奇怪的。通常,你有一个拥有和管理窗口的控制器对象,也充当应用程序的委托。

无论如何,仍然有可能得到……通过将main()函数更改为以下功能行为:

int main(int argc, const char * argv[]) {
[NSApplication sharedApplication];
Window *window = [[[Window alloc] init] autorelease];
NSApp.delegate = window;
[window makeKeyAndOrderFront:nil];
[NSApp run];
return 0;
}

有两个显著的变化。首先,您的问题是您没有将窗口实例设置为应用程序委托。第二,IIRC,你不应该直接调用-makeMainWindow;相反,该方法的存在是为了您可以根据需要重写它。如果您想在屏幕上显示窗口,请调用-makeKeyAndOrderFront:

打开一个文件应该在控制台显示日志行(如果你使用的是Xcode 12.5.1,如果需要调整日志窗口的大小来解决显示错误)。

在手动引用计数下,我相信这会泄漏内存,因为没有创建自动释放池,但我没有在控制台中看到任何通常的警告。无论如何,虽然这段代码可以工作,但它会导致一个相当不受欢迎的场景。在应用程序中没有主菜单,所以退出它你必须使用Dock。创建的窗口也很小,没有调整大小的功能,等等。

编辑:一个示例项目是在https://github.com/NSGod/OpenFile。

NSWindow的下面的子类应该允许你用唯一的'来保存文件。Jaf '扩展名,然后通过双击它重新打开文件到应用程序中。info。plist并不像我最初想象的那么重要;我没有修改Xcode创建的那个。对于这个非基于文档的应用程序来说,最重要的似乎是调用NSApplicationDelegate方法-(BOOL) application: openFile。NSApplicationDelegate被添加到NSWindow子类中,而不是像通常那样有一个单独的AppDelegate。当工作正常时,当双击.jaf文件后调用此方法时,您应该听到哔哔声;我找不到NSLog的输出。要在Xcode中运行演示,首先创建一个objc项目并删除main中的所有内容。M’文件并复制/粘贴以下源代码到其中。删除预先提供的AppDelegate类以避免重复的符号。在授权中,将App沙箱设置为NO,并将只读设置为零。JAF应用程序制作完成后,使用它将文件保存到桌面上,并使用'。于jaf的扩展。然后复制应用程序(在Finder中显示)并将其复制/粘贴到应用程序文件夹中。下一步至关重要;右键单击您刚刚制作的文件,并使用Get Info或Open With将文件设置为始终与新制作的应用程序一起打开。此时,您应该能够双击xxxx。Jaf文件,并让它打开到您的应用程序与一个可听到的哔哔声。

#import <Cocoa/Cocoa.h>
@interface Window : NSWindow <NSApplicationDelegate> {
NSTextView *txtView;
}
- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSWindowStyleMask)style backing:(NSBackingStoreType)backingStoreType defer:(BOOL)flag;
-(void) buildMenu;
-(void) openAction;
-(void) saveAction;
@end

@implementation Window
#define _wndW  700
#define _wndH  550
- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename {
NSLog(@"This comes from JAF : filename = %@.",filename);
NSBeep(); // Listen for this.
NSError *error;
NSURL *url = [NSURL fileURLWithPath:filename];
NSString *fileStr = [[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
if (!fileStr) {
NSLog(@"Unable to open file %@", error);
} else {
[txtView setString:fileStr];
}
return YES;
}
-(void) buildMenu {
// **** Menu Bar **** //
NSMenu *menubar = [NSMenu new];
[NSApp setMainMenu:menubar];
// **** App Menu **** //
NSMenuItem *appMenuItem = [NSMenuItem new];
NSMenu *appMenu = [NSMenu new];
[appMenu addItemWithTitle: @"Quit" action:@selector(terminate:) keyEquivalent:@"q"];
[appMenuItem setSubmenu:appMenu];
[menubar addItem:appMenuItem];
}

-(void) openAction {
NSOpenPanel *op = [NSOpenPanel openPanel];
[op setAllowedFileTypes:[NSArray arrayWithObjects: @"jaf", @"txt", nil]];
[op beginSheetModalForWindow: self completionHandler: ^(NSInteger returnCode) {
if (returnCode == NSModalResponseOK) {
NSURL *url = [op URL];
NSError *error;
NSString *fileStr = [[NSString alloc] initWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
if (!fileStr) {
NSLog(@"Unable to open file %@", error);
} else {
[self->txtView setString:fileStr];
}
}
}];
}
-(void) saveAction {
NSSavePanel *sp = [NSSavePanel savePanel];
[sp setTitle:@"Save contents to file"];
[sp setAllowedFileTypes:[NSArray arrayWithObjects: @"jaf", nil]];
[sp setNameFieldStringValue: @".jaf"];
[sp beginSheetModalForWindow: self completionHandler: ^(NSInteger returnCode) {
if (returnCode == NSModalResponseOK) {
NSURL *url = [sp URL];
NSString *viewStr = [[self->txtView textStorage] string];
NSError *err;
BOOL fileSaved = [viewStr writeToURL:url atomically:YES encoding:NSUTF8StringEncoding error:&err];
if (!fileSaved) { NSLog(@"Unable to save file due to error: %@", err);}
}
}];
}
- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSWindowStyleMask)style backing:(NSBackingStoreType)backingStoreType defer:(BOOL)flag {
self = [super initWithContentRect:NSMakeRect(0, 0, _wndW, _wndH) styleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable backing:NSBackingStoreBuffered defer:NO];
[self setTitle: @"Test window"];
[self center];
[self makeKeyAndOrderFront: nil];
// ****** NSTextView with Scroll ****** //
NSScrollView *scrlView = [[NSScrollView alloc] initWithFrame:NSMakeRect( 10, 10, _wndW - 20, _wndH - 80 )];
[[self contentView] addSubview:scrlView];
[scrlView setHasVerticalScroller: YES];
[scrlView setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ];
txtView = [[NSTextView alloc] initWithFrame:NSMakeRect( 0, 0, _wndW - 20, _wndH - 80 )];
[scrlView setDocumentView: txtView];
// **** Open Button **** //
NSButton *openBtn =[[NSButton alloc]initWithFrame:NSMakeRect( 30, _wndH - 50, 95, 30 )];
[openBtn setBezelStyle:NSBezelStyleRounded ];
[openBtn setTitle: @"Open"];
[openBtn setAutoresizingMask: NSViewMinYMargin];
[openBtn setAction: @selector (openAction)];
[[self contentView] addSubview: openBtn];
// **** Save Button **** //
NSButton *saveBtn =[[NSButton alloc]initWithFrame:NSMakeRect( 130, _wndH - 50, 95, 30 )];
[saveBtn setBezelStyle:NSBezelStyleRounded ];
[saveBtn setTitle: @"Save"];
[saveBtn setAutoresizingMask: NSViewMinYMargin];
[saveBtn setAction: @selector (saveAction)];
[[self contentView] addSubview: saveBtn];
return self;
}
- (BOOL)windowShouldClose:(id)sender {
[NSApp terminate:sender];
return YES;
}

@end
int main() {
NSApplication *application = [NSApplication sharedApplication];
Window *window = [[Window alloc]init];
[window buildMenu];
[application setDelegate:window];
[application activateIgnoringOtherApps:YES];
[NSApp run];
return 0;
}

最新更新