繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM