【问题标题】:How can I collect multiple openFile:(NSString *) events and then do something with them?如何收集多个 openFile:(NSString *) 事件,然后对它们进行处理?
【发布时间】:2012-02-13 15:06:05
【问题描述】:

我正在开发一个 Cocoa / Objective C++ 实用程序应用程序,并希望处理多个(瞬时)文件打开。为了处理文件打开部分,我在我的AppDelegate.mm 文件中有这个函数:

- (BOOL)application:(NSApplication*)app openFile:(NSString *)filename
{
    NSLog(@"Opening file %@", filename);

    // more C++ code here

    return YES;
}

文件被发送到 Quicksilver,我相信它将一个接一个地发送文件到应用程序(我认为 Finder 的“打开方式”会一次发送所有文件 - 因此可能使用 handleOpenApplicationEvent:(NSAppleEventDescriptor *)event 可能会更好那) - 但无论如何,应用程序将一个接一个地接收几个文件 - 几乎是瞬间 - 但不完全一起。这是 Console.app 显示的内容:

console-screenshot.png http://img109.imageshack.us/img109/1205/consolescreenshot.png

由于文件是单独发送的,但一个接一个,我的问题是如何收集所有发送的文件并用它们做一件事?例如,我想收集所有发送的文件路径,然后将它们一起显示在一个对话框中。

我可以想到一个可行的概念:将每个文件路径在收到时存储在一个数组中。同时,当收到第一个时,在后台设置 1-2 秒的延迟,然后有一个对话框显示所有特定变量的内容。这个概念是正确的还是有更好的方法来做到这一点?我是 Cocoa / Objective C++ 的新手——来自 PHP / Perl、bash 等语言。

我还希望这个帮助应用程序在完成后终止,但如果我正在等待文件,我如何在收到最后一个文件时终止应用程序?

如果我将[NSApp terminate:nil]; 添加到applicationDidFinishLaunching 函数中,应用程序实际上会在收到第一个文件后终止。

更新 - 更多说明

这是使用openFiles(复数)函数后的控制台: Picture 7.png http://img24.imageshack.us/img24/5715/picture7zc.png

我使用 Quicksilver 抓取一些文件,例如临时目录中的文件,然后选择“打开方式”,然后选择我正在创建的应用程序(名为 darn.app)

Screen Shot 2012-01-18 at 7.02.45 PM.png http://img9.imageshack.us/img9/4171/screenshot20120118at702.png

但使用 Finder 似乎可以正常工作:

Screen Shot 2012-01-18 at 7.09.08 PM.png http://img832.imageshack.us/img832/8858/screenshot20120118at709.png

...结果为 consolea.app:

Picture 8.png http://img24.imageshack.us/img24/2812/picture8fe.png

我确实询问了 Quicksilver 开发人员,他们确认 QS 确实使用 Open With 操作一次打开一个文件,他们承认这与 Finder 的做法不同,但他们认为这是预期的。所以也许 Darren 是对的 - 计时器可能是最好的方法......

【问题讨论】:

  • 您到底是如何使用 Quicksilver 的?这个问题的答案可能会建议一种向您的应用程序发送附加信息的方法,该信息可用于确定何时收到所有文件。

标签: macos cocoa


【解决方案1】:

系统无法知道是否会有更多的文件打开请求,因此不仅没有提供表示最后一个请求的方法,也没有可能的方法。

作为第一个问题的计时器的替代方案,您可以立即开始处理文件并在对话框中显示每个文件,以便用户看到列表增长。这并没有解决第二个问题(在收到所有文件后终止应用程序)。

如果您确实使用了计时器,请确保在每个application:openFile: 之后重置它。

【讨论】:

    【解决方案2】:

    尝试实现-application:openFiles: 而不是-application:openFile:

    - (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames
    {
        NSLog(@"Opening multiple files %@", filenames);
    }
    

    它处理从 Finder 接收多个文件。

    如果这不适用于您的 Quicksilver 设置,那么计时器可能是最好的选择。

    在 AppDelegate 的 -init 方法中设置计时器。

    @implementation MyAppDelegate {
        NSMutableArray* _files;
    }
    
    - (id)init {
        if (self = [super init]) {
            _files = [[NSMutableArray alloc] initWithCapacity:10];
    
            [self performSelector:@selector(processFiles) 
                       withObject:nil 
                       afterDelay:1.0]; // one second delay
        }
        return self;
    }
    

    在 -application:openFile 中:将文件收集到一个数组中并重置计时器。

    - (BOOL)application:(NSApplication*)app openFile:(NSString*)filename {
        NSAssert(_files != nil, @"Timer already fired");
    
        [_files addObject:filename];
    
        [NSObject cancelPreviousPerformRequestsWithTarget:self];
        [self performSelector:@selector(processFiles) 
                   withObject:nil 
                   afterDelay:1.0];
    } 
    

    当计时器触发时,处理收集的文件,然后退出应用程序。

    -(void)processFiles
    
        // Process the _files
    
        [_files release];
        _files = nil;
        [NSApp terminate:nil];
    }
    

    【讨论】:

    • 遗憾的是,Quicksilver 似乎不会使用application:openFiles:。我相信相关的方法是openFile:FSActionsopenFile:with:
    • 谢谢@Darren - 你的回答太棒了。此外,我认为 outis 对 Quicksilver 的看法是正确的——我更新了这个问题,增加了一些关于使用 QS 的注释以及它给出的 vs finder 的结果。 :) 期待尝试计时器方法。
    【解决方案3】:

    我正在启动一个带有多个命令行参数的 App 可执行文件。

    MyApp.app/Contents/MacOS/MyApp file1 file2 file3
    

    每个参数生成一个单独的 application:openFile(s) 调用,如上所述。然而,在这种情况下 applicationDidFinishLaunching 直到所有 openFile 调用之后才被调用,因此很容易做这样的事情:

    NSMutableArray *_allFiles = nil;
    
    - (void)applicationDidFinishLaunching:(NSNotification *)notification {
      [self handleFiles:_allFiles];
    }
    
    - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename {
      [self application:theApplication openFiles:[NSArray arrayWithObject:filename]];
      return YES;
    }
    
    - (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames {
      if(!_allFiles) _allFiles = [NSMutableArray arrayWithCapacity:8];
      [_allFiles addObjectsFromArray:filenames];
    }
    

    此方法也适用于在 Finder 中使用“打开方式”打开多个文件。如果 Quicksilver 以相同的方式处理多个文件,我不会感到惊讶,因此这种简单的方法可以为您工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-05-15
      • 2014-12-09
      • 1970-01-01
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多