0

我编写了一个可以作为服务调用的应用程序(通过右键单击 Finder 中的文件并选择使用我的应用程序打开它),但是这样做会产生一些不需要的副作用。

服务目标方法示例:

- (void)doSomething:(NSPasteboard *)pboard userData:(NSString *)userData error:(NSString **)error {
    NSArray *files = [pboard propertyListForType:NSFilenamesPboardType];
    NSLog(@"Selected file(s): %@", files);
    [self.anotherWindow makeKeyAndOrderFront:self];
}

1)当应用程序以这种方式启动时(即使已经在调试模式下打开),我似乎无法从 doSomething 函数访问其他窗口/控件。例如,上面显示“anotherWindow”的尝试不会产生错误,但不会“做”任何事情。根据堆栈跟踪,当从 -doSomething 检查时,所有 gui 组件的值都为 0x0000000000000000 - 但应用程序已显示并且功能齐全。只有 -doSomething 我无法联系到他们。从 -doSomething 与 -applicationDidFinishLaunching 检查时,“self”也有不同的值。我不确定 -doSomething 如何或为什么使用未初始化的组件获取不同的 self/AppDelegate。似乎由 [NSApp setServicesProvider:self] 修复;

2)我不清楚系统如何决定在调用服务时启动哪个应用程序副本,但它通常不会选择我想要的那个。我在 /Debug 中有一个副本,在 /Release 中有一个副本,在我的桌面上有一个副本......如果我删除一个,它会打开另一个文件(某种回退链?)。如何配置服务(在代码中或通过 .plist)以打开此应用程序的特定版本/位置?但这是一台开发机器。如果我发布一个安装到 /Applications 的可分发文件,我真的需要担心这个吗?

4

1 回答 1

0

1) 仔细检查您的 XIB 以确保您已正确连接所有内容,然后尝试使用NSLog上面设置的断点启动应用程序并验证该self.anotherWindow点是否指向您想要的位置。如果由于某种原因断点没有触发,请尝试添加:

NSLog( @"Window: %@", self.anotherWindow);

确保一切都已初始化并已连接

2) 系统用于Launch Services确定启动哪个版本的应用程序。通常它是最近添加到系统中的版本(这将导致Launch Services数据库被修改),但根据您的系统配置方式,它可能不是您期望的版本。

您可以使用以下方法手动查询和修改启动服务数据库:

/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister

(是的,真的很长的路)。如果您使用该-dump选项,它将为您提供系统中的所有数据(通过管道输入文件并搜索它以更好地了解正在发生的事情)。如果您搜索捆绑包 ID,您将看到该应用程序的所有条目。通常,最近获胜,但您可以强制重新加载(说明如下)。

如果您只想基于特定二进制文件强制重新加载,请使用-f标志和应用程序路径:

..../lsregister -f /Applications/Foo.app

您还可以使用-u显式取消注册某些内容。

希望这能让您了解这里发生了什么。

于 2013-11-10T22:52:47.563 回答