[英]How do assign a type of file to my app on Mac
我尝试为我的应用程序分配文件类型。
在 Info.plist 我添加:
<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
直接调用-makeMainWindow
; 相反,该方法存在,因此您可以根据需要覆盖它。 如果要在屏幕上显示窗口,请调用-makeKeyAndOrderFront:
。
打开文件应该会在控制台中显示记录的行(如果您使用的是 Xcode 12.5.1,如果需要解决显示错误,请调整日志窗口的大小)。
在手动引用计数下,我相信这会泄漏内存,因为没有创建自动释放池,但我没有在控制台中看到任何常见的警告。 无论如何,虽然此代码有效,但会导致相当不理想的情况。 应用程序中没有主菜单,因此要退出它,您必须使用 Dock。 创建的窗口也很小,没有调整大小等功能。
NSWindow 的以下子类应该允许您使用唯一的“.jaf”扩展名保存文件,然后通过双击将文件重新打开到应用程序中。 info.plist 并不像我最初想象的那么重要; 我没有改变由 Xcode 创建的那个。 对于这个非基于文档的应用程序来说,最重要的似乎是调用 NSApplicationDelegate 方法 -(BOOL) 应用程序:openFile。 NSApplicationDelegate 被添加到 NSWindow 子类中,而不是像通常那样有一个单独的 AppDelegate。 正常工作时,双击 .jaf 文件后调用此方法时,您应该会听到蜂鸣声; 我找不到 NSLog 输出。 要在 Xcode 中运行演示,首先创建一个 objc 项目并删除“main.m”文件中的所有内容,然后将以下源代码复制/粘贴到其中。 删除预先提供的 AppDelegate 类以避免重复符号。 在权利中将 App Sandbox 设置为 NO 并将只读设置为零。 制作 JAF 应用程序后,使用它以“.jaf”扩展名将文件保存到桌面。 然后制作应用程序的副本(显示在 Finder 中)并将其复制/粘贴到应用程序文件夹中。 下一步很关键; 右键单击您刚刚创建的文件,然后使用“获取信息”或“打开方式”将文件设置为始终使用新创建的应用程序打开。 此时,您应该能够双击 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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.