我正在使用Cocoa / Objective C ++实用程序,并希望处理多个(即时)文件打开。要处理文件打开部分,我在AppDelegate.mm
文件中有这个功能:
- (BOOL)application:(NSApplication*)app openFile:(NSString *)filename
{
NSLog(@"Opening file %@", filename);
// more C++ code here
return YES;
}
这些文件正被发送到Quicksilver,我相信这些文件将一个接一个地发送到应用程序(Finder'' Open With"我认为一次发送所有文件 - 所以可能使用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,我会抓取一些文件,比如temp目录中的文件,然后选择" Open With"然后我创建的应用程序(名为darn.app)
但是使用Finder似乎工作正常:
...导致consolea.app:
Picture 8.png http://img24.imageshack.us/img24/2812/picture8fe.png
我确实问过Quicksilver的开发人员,他们确认QS确实打开一个文件,一次打开文件,他们承认这与Finder的做法不同,但他们认为这是预期的。也许Darren是对的 - 计时器可能是最好的方式......
答案 0 :(得分:5)
尝试实施-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;
}
In -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];
}
答案 1 :(得分:1)
系统无法知道是否有更多的文件打开请求,所以不仅没有提供表示最后一个请求的方法,也没有可能的方法。
作为第一个问题的计时器的替代方案,您可以立即开始处理文件并在对话框中显示每个文件,这样用户就会看到列表增长。这不解决第二个问题(在收到所有文件后终止应用程序)。
如果您使用计时器,请确保在每个application:openFile:
之后重置计时器。
答案 2 :(得分:0)
我正在使用多个命令行参数启动App可执行文件。
MyApp.app/Contents/MacOS/MyApp file1 file2 file3
每个参数都会生成一个单独的应用程序:openFile(s)调用,如上所述。但是,在这种情况下,在所有openFile调用之后才调用applicationDidFinishLaunching,因此很容易做到这样的事情:
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以相同的方式处理多个文件,我不会感到惊讶,所以这个简单的方法可以为你工作。